Oolite 1.91.0.7644-241112-7f5034b
Loading...
Searching...
No Matches
OOLightParticleEntity.m
Go to the documentation of this file.
1/*
2
3OOLightParticleEntity.m
4
5
6Oolite
7Copyright (C) 2004-2013 Giles C Williams and contributors
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
27#import "Universe.h"
28#import "PlayerEntity.h"
29#import "OOTexture.h"
30#import "OOColor.h"
33#import "OOMacroOpenGL.h"
35#import "MyOpenGLView.h"
36
37
38#define PARTICLE_DISTANCE_SCALE_LOW 12.0
39#define PARTICLE_DISTANCE_SCALE_HIGH 36.0
40
41
43
44
45@interface OOLightParticleEntity (Private)
46
47+ (void) resetGraphicsState;
48
49@end
50
51
52@implementation OOLightParticleEntity
53
54- (id) initWithDiameter:(float)diameter
55{
56 if ((self = [super init]))
57 {
58 _diameter = diameter;
59 no_draw_distance = pow(diameter / 2.0, M_SQRT2) * NO_DRAW_DISTANCE_FACTOR * NO_DRAW_DISTANCE_FACTOR;
60 no_draw_distance *= [UNIVERSE reducedDetail] ? PARTICLE_DISTANCE_SCALE_LOW : PARTICLE_DISTANCE_SCALE_HIGH;
61
62 _colorComponents[0] = 1.0f;
63 _colorComponents[1] = 1.0f;
64 _colorComponents[2] = 1.0f;
65 _colorComponents[3] = 1.0f;
66
67 [self setScanClass:CLASS_NO_DRAW];
68 [self setStatus:STATUS_EFFECT];
69 }
70
71 return self;
72}
73
74
75- (float) diameter
76{
77 return _diameter;
78}
79
80
81- (void) setDiameter:(float)diameter
82{
83 _diameter = diameter;
84}
85
86
87- (void) setColor:(OOColor *)color
88{
89 [color getRed:&_colorComponents[0] green:&_colorComponents[1] blue:&_colorComponents[2] alpha:&_colorComponents[3]];
90}
91
92
93- (void) setColor:(OOColor *)color alpha:(GLfloat)alpha
94{
95 [self setColor:color];
96 _colorComponents[3] = alpha;
97}
98
99
100- (void) drawSubEntityImmediate:(bool)immediate translucent:(bool)translucent
101{
102 if (!translucent) return;
103
104 /* TODO: someone will inevitably build a ship so big that individual
105 zero_distances are necessary for flashers, if they haven't already.
106 -- Ahruman 2009-09-20
107 */
108 cam_zero_distance = [[self owner] camZeroDistance];
109 if (no_draw_distance <= cam_zero_distance) return;
110
111 Entity *father = [self owner];
112 Entity *last = nil;
113 HPVector abspos = position;
114
115 while (father != nil && father != last && father != NO_TARGET)
116 {
117 OOMatrix rM = [father drawRotationMatrix];
118 abspos = HPvector_add(OOHPVectorMultiplyMatrix(abspos, rM), [father position]);
119 last = father;
120
121 if (![father isSubEntity]) break;
122 father = [father owner];
123 }
124
125 OOMatrix temp_matrix = OOGLPopModelView();
127
128 /* Flashers are drawn using the absolute view matrix */
129 OOGLLoadModelView([UNIVERSE viewMatrix]);
130 /* ...modified by the aggregate translation calculated above */
131 OOGLTranslateModelView(HPVectorToVector(HPvector_subtract(abspos,[PLAYER viewpointPosition]))); // move to camera-relative position
132 [self drawImmediate:immediate translucent:translucent];
133
134 OOGLLoadModelView(temp_matrix);
135}
136
137
138- (void) drawImmediate:(bool)immediate translucent:(bool)translucent
139{
140 if (!translucent) return;
141 if ([UNIVERSE breakPatternHide] && ![self isImmuneToBreakPatternHide])
142 {
143 Entity *father = [self owner];
144 while (father != nil && father != NO_TARGET)
145 {
146 if (![father isSubEntity]) break;
147 father = [father owner];
148 }
149 if (![father isImmuneToBreakPatternHide])
150 {
151 return;
152 }
153 }
154 if (no_draw_distance <= cam_zero_distance) return;
155
158
159 OOGL(glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT));
160 OOGL(glEnable(GL_BLEND));
161 OOGL(glBlendFunc(GL_SRC_ALPHA, GL_ONE));
162
163 OOGL(glEnable(GL_TEXTURE_2D));
164 OOGL(glDepthMask(GL_FALSE));
165
166 GLfloat distanceAttenuation = cam_zero_distance / no_draw_distance;
167 distanceAttenuation = 1.0 - distanceAttenuation;
168 GLfloat components[4] = { _colorComponents[0], _colorComponents[1], _colorComponents[2], _colorComponents[3] * distanceAttenuation };
169 OOGL(glColor4fv(components));
170
171 OOGL(glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, components));
172 OOGL(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND));
173
174 OOViewID viewDir = [UNIVERSE viewDirection];
175 if (viewDir != VIEW_GUI_DISPLAY) OOGLMultModelView([PLAYER drawRotationMatrix]);
176 [[self texture] apply];
177
178 /* NOTE: nominal diameter is actual radius, because of the black border
179 in the texture. However, the offset along the view axis is not
180 affected by the border and needs to be scaled.
181 -- Ahruman 2009-12-20
182 */
183 float viewOffset = _diameter * 0.5f;
184
185 OOGLBEGIN(GL_QUADS);
186 switch (viewDir)
187 {
188 case VIEW_FORWARD:
189 case VIEW_GUI_DISPLAY:
190 glTexCoord2f(0.0, 1.0);
191 glVertex3f(-_diameter, -_diameter, -viewOffset);
192
193 glTexCoord2f(1.0, 1.0);
194 glVertex3f(_diameter, -_diameter, -viewOffset);
195
196 glTexCoord2f(1.0, 0.0);
197 glVertex3f(_diameter, _diameter, -viewOffset);
198
199 glTexCoord2f(0.0, 0.0);
200 glVertex3f(-_diameter, _diameter, -viewOffset);
201 break;
202
203 case VIEW_AFT:
204 glTexCoord2f(0.0, 1.0);
205 glVertex3f(_diameter, -_diameter, viewOffset);
206
207 glTexCoord2f(1.0, 1.0);
208 glVertex3f(-_diameter, -_diameter, viewOffset);
209
210 glTexCoord2f(1.0, 0.0);
211 glVertex3f(-_diameter, _diameter, viewOffset);
212
213 glTexCoord2f(0.0, 0.0);
214 glVertex3f(_diameter, _diameter, viewOffset);
215 break;
216
217 case VIEW_STARBOARD:
218 glTexCoord2f(0.0, 1.0);
219 glVertex3f(-viewOffset, -_diameter, _diameter);
220
221 glTexCoord2f(1.0, 1.0);
222 glVertex3f(-viewOffset, -_diameter, -_diameter);
223
224 glTexCoord2f(1.0, 0.0);
225 glVertex3f(-viewOffset, _diameter, -_diameter);
226
227 glTexCoord2f(0.0, 0.0);
228 glVertex3f(-viewOffset, _diameter, _diameter);
229 break;
230
231 case VIEW_PORT:
232 glTexCoord2f(0.0, 1.0);
233 glVertex3f(viewOffset, -_diameter, -_diameter);
234
235 glTexCoord2f(1.0, 1.0);
236 glVertex3f(viewOffset, -_diameter, _diameter);
237
238 glTexCoord2f(1.0, 0.0);
239 glVertex3f(viewOffset, _diameter, _diameter);
240
241 glTexCoord2f(0.0, 0.0);
242 glVertex3f(viewOffset, _diameter, -_diameter);
243 break;
244
245 case VIEW_CUSTOM:
246 {
247 PlayerEntity *player = PLAYER;
248 Vector vi = [player customViewRightVector]; vi.x *= _diameter; vi.y *= _diameter; vi.z *= _diameter;
249 Vector vj = [player customViewUpVector]; vj.x *= _diameter; vj.y *= _diameter; vj.z *= _diameter;
250 Vector vk = [player customViewForwardVector]; vk.x *= viewOffset; vk.y *= viewOffset; vk.z *= viewOffset;
251 glTexCoord2f(0.0, 1.0);
252 glVertex3f(-vi.x -vj.x -vk.x, -vi.y -vj.y -vk.y, -vi.z -vj.z -vk.z);
253 glTexCoord2f(1.0, 1.0);
254 glVertex3f(+vi.x -vj.x -vk.x, +vi.y -vj.y -vk.y, +vi.z -vj.z -vk.z);
255 glTexCoord2f(1.0, 0.0);
256 glVertex3f(+vi.x +vj.x -vk.x, +vi.y +vj.y -vk.y, +vi.z +vj.z -vk.z);
257 glTexCoord2f(0.0, 0.0);
258 glVertex3f(-vi.x +vj.x -vk.x, -vi.y +vj.y -vk.y, -vi.z +vj.z -vk.z);
259 }
260 break;
261
262 default:
263 glTexCoord2f(0.0, 1.0);
264 glVertex3f(-_diameter, -_diameter, -_diameter);
265
266 glTexCoord2f(1.0, 1.0);
267 glVertex3f(_diameter, -_diameter, -_diameter);
268
269 glTexCoord2f(1.0, 0.0);
270 glVertex3f(_diameter, _diameter, -_diameter);
271
272 glTexCoord2f(0.0, 0.0);
273 glVertex3f(-_diameter, _diameter, -_diameter);
274 break;
275 }
276 OOGLEND();
277
278 OOGL(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
279 OOGL(glPopAttrib());
280
282}
283
284
285- (OOTexture *) texture
286{
288}
289
290
291+ (void) setUpTexture
292{
293 if (sBlobTexture == nil)
294 {
295 sBlobTexture = [[OOTexture textureWithName:@"oolite-particle-blur.png"
296 inFolder:@"Textures"
297 options:kOOTextureMinFilterMipMap | kOOTextureMagFilterLinear | kOOTextureAlphaMask
298 anisotropy:kOOTextureDefaultAnisotropy / 2.0
299 lodBias:0.0] retain];
300 [[OOGraphicsResetManager sharedManager] registerClient:(id<OOGraphicsResetClient>)[OOLightParticleEntity class]];
301 }
302}
303
304
305+ (OOTexture *) defaultParticleTexture
306{
307 if (sBlobTexture == nil) [self setUpTexture];
308 return sBlobTexture;
309}
310
311
312+ (void) resetGraphicsState
313{
314 [sBlobTexture release];
316}
317
318
319- (BOOL) isEffect
320{
321 return YES;
322}
323
324
325- (BOOL) canCollide
326{
327 return NO;
328}
329
330
331
332#ifndef NDEBUG
333- (NSSet *) allTextures
334{
335 return [NSSet setWithObject:[self texture]];
336}
337#endif
338
339@end
#define NO_DRAW_DISTANCE_FACTOR
Definition Entity.h:46
static OOTexture * sBlobTexture
#define PARTICLE_DISTANCE_SCALE_HIGH
#define PARTICLE_DISTANCE_SCALE_LOW
#define OO_ENTER_OPENGL()
#define M_SQRT2
Definition OOMaths.h:91
HPVector OOHPVectorMultiplyMatrix(HPVector v, OOMatrix m)
Definition OOMatrix.m:145
void OOGLLoadModelView(OOMatrix matrix)
void OOGLPushModelView(void)
void OOGLTranslateModelView(Vector vector)
void OOGLMultModelView(OOMatrix matrix)
OOMatrix OOGLPopModelView(void)
#define OOGLBEGIN
Definition OOOpenGL.h:253
@ OPENGL_STATE_ADDITIVE_BLENDING
Definition OOOpenGL.h:125
#define OOVerifyOpenGLState()
Definition OOOpenGL.h:136
#define OOSetOpenGLState(STATE)
Definition OOOpenGL.h:135
#define OOGL(statement)
Definition OOOpenGL.h:251
#define OOGLEND
Definition OOOpenGL.h:254
return nil
OOViewID
Definition OOTypes.h:43
@ NO_TARGET
Definition OOTypes.h:194
#define PLAYER
#define UNIVERSE
Definition Universe.h:833
void setScanClass:(OOScanClass sClass)
Definition Entity.m:799
void setStatus:(OOEntityStatus stat)
Definition Entity.m:787
id owner()
Definition Entity.m:583
OOMatrix drawRotationMatrix()
Definition Entity.m:879
void getRed:green:blue:alpha:(float *red,[green] float *green,[blue] float *blue,[alpha] float *alpha)
Definition OOColor.m:368
void registerClient:(id< OOGraphicsResetClient > client)
OOGraphicsResetManager * sharedManager()
oneway void release()
Definition OOTexture.m:614
id textureWithName:inFolder:options:anisotropy:lodBias:(NSString *name,[inFolder] NSString *directory,[options] OOTextureFlags options,[anisotropy] GLfloat anisotropy,[lodBias] GLfloat lodBias)
Definition OOTexture.m:134
Vector customViewRightVector
Vector customViewUpVector
Vector customViewForwardVector