33#import "MyOpenGLView.h"
39#define kOverallAlpha 1.0f
40#define kTimeStep 0.05f
41#define kFadeLevel1 0.4f
42#define kFadeLevel2 0.2f
43#define kFadeLevel3 0.02f
44#define kScaleLevel1 1.0f
45#define kScaleLevel2 0.8f
46#define kScaleLevel3 0.6f
51@interface OOExhaustPlumeEntity (Private)
54- (
Frame) frameAtTime:(
double) t_frame fromFrame:(
Frame) frame_zero;
61+ (id) exhaustForShip:(
ShipEntity *)ship withDefinition:(NSArray *)definition andScale:(
float)scale
63 return [[[
self alloc] initForShip:ship withDefinition:definition andScale:(float)scale] autorelease];
67- (id) initForShip:(
ShipEntity *)ship withDefinition:(NSArray *)definition andScale:(
float)scaleFactor
69 if ([definition
count] == 0)
75 if ((
self = [super init]))
78 HPVector pos = { [definition oo_floatAtIndex:0]*scaleFactor, [definition oo_floatAtIndex:1]*scaleFactor, [definition oo_floatAtIndex:2]*scaleFactor };
79 [
self setPosition:pos];
81 Vector scale = { [definition oo_floatAtIndex:3]*scaleFactor, [definition oo_floatAtIndex:4]*scaleFactor, [definition oo_floatAtIndex:5] };
82 [
self setScale:scale];
95- (void) setScale:(Vector)scale
97 _exhaustScale = scale;
98 if (scale.z < 0.5 || scale.z > 2.0)
100 _exhaustScale.z = 1.0;
111- (double)findCollisionRadius
113 return collision_radius;
124 if (
EXPECT_NOT(ship ==
nil || ![ship isVisible] || ([ship isPlayer] && [ship suppressFlightNotifications])))
return;
129 [
self saveToLastFrame];
134 collision_radius = 0;
137 GLfloat ex_emissive[4];
146 .timeframe = [UNIVERSE getTime],
147 .orientation = shipQrotation,
156 GLfloat hyper_fade = 8.0f / (8.0f + speed * speed * speed);
158 GLfloat flare_factor = fmaxf(speed,1.0) * ex_emissive[3] * hyper_fade;
159 GLfloat red_factor = speed * ex_emissive[0] * (
ranrot_rand() % 11) * 0.1f;
160 GLfloat green_factor = speed * ex_emissive[1] * hyper_fade;
174 HPVector currentPos = ship->
position;
177 vfwd = vector_multiply_scalar(vfwd, spd);
183 zero.
position = make_HPvector(currentPos.x + vi.x * position.x + vj.x * position.y + vk.x * position.z,
184 currentPos.y + vi.y * position.x + vj.y * position.y + vk.y * position.z,
185 currentPos.z + vi.z * position.x + vj.z * position.y + vk.z * position.z);
187 GLfloat speedScale = fminf(1.0f,speed * 5.0f);
189 GLfloat exhaust_factor = _exhaustScale.z;
190 GLfloat i01 = -0.00f * hyper_fade;
191 GLfloat i03 = -0.12f * exhaust_factor;
192 GLfloat i06 = -0.25f * exhaust_factor;
193 GLfloat i08 = -0.32f * exhaust_factor;
194 GLfloat i10 = -0.40f * exhaust_factor;
195 GLfloat q01 = i01/i10;
196 GLfloat q03 = i03/i10;
197 GLfloat q06 = i06/i10;
198 GLfloat q08 = i08/i10;
199 GLfloat r01 = 1.0f - q01;
200 GLfloat r03 = 1.0f - q03;
201 GLfloat r06 = 1.0f - q06;
202 GLfloat r08 = 1.0f - q08;
203 Frame f01 = [
self frameAtTime: i01 fromFrame: zero];
204 Vector b01 = make_vector(r01 * i01 * vfwd.x, r01 * i01 * vfwd.y, r01 * i01 * vfwd.z);
205 Frame f03 = [
self frameAtTime: i03 fromFrame: zero];
206 Vector b03 = make_vector(r03 * i03 * vfwd.x, r03 * i03 * vfwd.y, r03 * i03 * vfwd.z);
207 Frame f06 = [
self frameAtTime: i06 fromFrame: zero];
208 Vector b06 = make_vector(r06 * i06 * vfwd.x, r06 * i06 * vfwd.y, r06 * i06 * vfwd.z);
209 Frame f08 = [
self frameAtTime: i08 fromFrame: zero];
210 Vector b08 = make_vector(r08 * i08 * vfwd.x, r08 * i08 * vfwd.y, r08 * i08 * vfwd.z);
211 Frame f10 = [
self frameAtTime: i10 fromFrame: zero];
222 ex_emissive[1] = green_factor;
223 ex_emissive[0] = red_factor;
224 vertex = HPvector_add(f01.
position, vectorToHPVector(b01));
225 collision_radius = HPmagnitude(HPvector_subtract(vertex, currentPos));
226 _vertices[iv++] = vertex.x;
227 _vertices[iv++] = vertex.y;
228 _vertices[iv++] = vertex.z;
229 _exhaustBaseColors[ci++] = ex_emissive[0];
230 _exhaustBaseColors[ci++] = ex_emissive[1];
231 _exhaustBaseColors[ci++] = ex_emissive[2];
232 _exhaustBaseColors[ci++] = ex_emissive[3];
236 Vector j1 = cross_product(master_i, k1);
237 Vector i1 = vector_multiply_scalar(cross_product(j1, k1), _exhaustScale.x * speedScale);
238 j1 = vector_multiply_scalar(j1, _exhaustScale.y * speedScale);
240 for (i = 0; i < 8; i++)
243 vectorToHPVector(vector_add(b01,
244 vector_add(vector_multiply_scalar(i1,s1[i]),
245 vector_multiply_scalar(j1,c1[i])))));
246 length = HPmagnitude(HPvector_subtract(vertex, currentPos));
247 if (length > collision_radius)
249 collision_radius = length;
251 _vertices[iv++] = vertex.x;
252 _vertices[iv++] = vertex.y;
253 _vertices[iv++] = vertex.z;
254 _exhaustBaseColors[ci++] = ex_emissive[0];
255 _exhaustBaseColors[ci++] = ex_emissive[1];
256 _exhaustBaseColors[ci++] = ex_emissive[2];
257 _exhaustBaseColors[ci++] = ex_emissive[3];
265 i1 = vector_multiply_scalar(cross_product(j1, k1), _exhaustScale.x *
kScaleLevel1 * speedScale);
266 j1 = vector_multiply_scalar(cross_product(master_i, k1), _exhaustScale.y *
kScaleLevel1 * speedScale);
267 for (i = 0; i < 8; i++)
271 vectorToHPVector(vector_add(b03,
272 vector_add(vector_multiply_scalar(i1,s1[i]),
273 vector_add(vector_multiply_scalar(j1,c1[i]),
274 vector_multiply_scalar(k1,r1))))));
275 length = HPmagnitude(HPvector_subtract(vertex, currentPos));
276 if (length > collision_radius)
278 collision_radius = length;
280 _vertices[iv++] = vertex.x;
281 _vertices[iv++] = vertex.y;
282 _vertices[iv++] = vertex.z;
283 _exhaustBaseColors[ci++] = ex_emissive[0];
284 _exhaustBaseColors[ci++] = ex_emissive[1];
285 _exhaustBaseColors[ci++] = ex_emissive[2];
286 _exhaustBaseColors[ci++] = ex_emissive[3];
294 i1 = vector_multiply_scalar(cross_product(j1, k1), 0.8f * _exhaustScale.x *
kScaleLevel2 * speedScale);
295 j1 = vector_multiply_scalar(cross_product(master_i, k1), 0.8f * _exhaustScale.y *
kScaleLevel2 * speedScale);
296 for (i = 0; i < 8; i++)
300 vectorToHPVector(vector_add(b06,
301 vector_add(vector_multiply_scalar(i1,s1[i]),
302 vector_add(vector_multiply_scalar(j1,c1[i]),
303 vector_multiply_scalar(k1,r1))))));
304 length = HPmagnitude(HPvector_subtract(vertex, currentPos));
305 if (length > collision_radius)
307 collision_radius = length;
309 _vertices[iv++] = vertex.x;
310 _vertices[iv++] = vertex.y;
311 _vertices[iv++] = vertex.z;
312 _exhaustBaseColors[ci++] = ex_emissive[0];
313 _exhaustBaseColors[ci++] = ex_emissive[1];
314 _exhaustBaseColors[ci++] = ex_emissive[2];
315 _exhaustBaseColors[ci++] = ex_emissive[3];
322 i1 = vector_multiply_scalar(cross_product(j1, k1), 0.5f * _exhaustScale.x *
kScaleLevel3 * speedScale);
323 j1 = vector_multiply_scalar(cross_product(master_i, k1), 0.5f * _exhaustScale.y *
kScaleLevel3 * speedScale);
324 for (i = 0; i < 8; i++)
328 vectorToHPVector(vector_add(b08,
329 vector_add(vector_multiply_scalar(i1,s1[i]),
330 vector_add(vector_multiply_scalar(j1,c1[i]),
331 vector_multiply_scalar(k1,r1))))));
332 length = HPmagnitude(HPvector_subtract(vertex, currentPos));
333 if (length > collision_radius)
335 collision_radius = length;
337 _vertices[iv++] = vertex.x;
338 _vertices[iv++] = vertex.y;
339 _vertices[iv++] = vertex.z;
340 _exhaustBaseColors[ci++] = ex_emissive[0];
341 _exhaustBaseColors[ci++] = ex_emissive[1];
342 _exhaustBaseColors[ci++] = ex_emissive[2];
343 _exhaustBaseColors[ci++] = ex_emissive[3];
346 ex_emissive[3] = 0.0;
347 ex_emissive[1] = 0.0;
348 ex_emissive[0] = 0.0;
349 length = HPmagnitude(HPvector_subtract(vertex, currentPos));
350 if (length > collision_radius)
352 collision_radius = length;
357 _exhaustBaseColors[ci++] = ex_emissive[0];
358 _exhaustBaseColors[ci++] = ex_emissive[1];
359 _exhaustBaseColors[ci++] = ex_emissive[2];
360 _exhaustBaseColors[ci++] = ex_emissive[3];
365static GLuint
tfan1[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 1 };
368static GLuint
tstr1[9] = { 1, 5, 9, 13, 17, 21, 25, 29, 33 };
369static GLuint
tstr2[9] = { 2, 6, 10, 14, 18, 22, 26, 30, 33 };
370static GLuint
tstr3[9] = { 3, 7, 11, 15, 19, 23, 27, 31, 33 };
371static GLuint
tstr4[9] = { 4, 8, 12, 16, 20, 24, 28, 32, 33 };
380static GLfloat
pA[6] = { 0.01, 0.0, 2.0, 4.0, 6.0, 10.0 };
383- (void) drawSubEntityImmediate:(
bool)immediate translucent:(
bool)translucent
385 if (!translucent)
return;
388 if ([ship speedFactor] <= 0.001f)
return;
396 HPVector cam = [PLAYER viewpointPosition];
397 for (
unsigned n=0;n<34*3;n++)
402 _glVertices[n] = (GLfloat)(_vertices[n] - cam.x);
405 _glVertices[n] = (GLfloat)(_vertices[n] - cam.y);
408 _glVertices[n] = (GLfloat)(_vertices[n] - cam.z);
413 OOGL(glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT));
415 OOGL(glDisable(GL_LIGHTING));
416 OOGL(glEnable(GL_BLEND));
417 OOGL(glDepthMask(GL_FALSE));
418 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
419 OOGL(glEnable(GL_TEXTURE_2D));
420 [[
self texture] apply];
423 OOGL(glShadeModel(GL_SMOOTH));
425 OOGL(glEnableClientState(GL_COLOR_ARRAY));
426 OOGL(glVertexPointer(3, GL_FLOAT, 0, _glVertices));
427 OOGL(glColorPointer(4, GL_FLOAT, 0, _exhaustBaseColors));
429 double intpart, dphase = 1.0-modf((
double)[
UNIVERSE getTime]*2.5,&intpart);
430 GLfloat phase = (GLfloat)dphase;
432 GLfloat texCoords[68] = {
435 0.1, phase+
pA[1], 0.1, phase+
pA[1],
436 0.1, phase+
pA[1], 0.1, phase+
pA[1],
437 0.9, phase+
pA[1], 0.9, phase+
pA[1],
438 0.9, phase+
pA[1], 0.9, phase+
pA[1],
440 0.1, phase+
pA[2], 0.1, phase+
pA[2],
441 0.1, phase+
pA[2], 0.1, phase+
pA[2],
442 0.9, phase+
pA[2], 0.9, phase+
pA[2],
443 0.9, phase+
pA[2], 0.9, phase+
pA[2],
445 0.1, phase+
pA[3], 0.1, phase+
pA[3],
446 0.1, phase+
pA[3], 0.1, phase+
pA[3],
447 0.9, phase+
pA[3], 0.9, phase+
pA[3],
448 0.9, phase+
pA[3], 0.9, phase+
pA[3],
450 0.1, phase+
pA[4], 0.1, phase+
pA[4],
451 0.1, phase+
pA[4], 0.1, phase+
pA[4],
452 0.9, phase+
pA[4], 0.9, phase+
pA[4],
453 0.9, phase+
pA[4], 0.9, phase+
pA[4],
457 OOGL(glTexCoordPointer(2, GL_FLOAT, 0, texCoords));
460 if ([[
self owner] isPlayer] && [
UNIVERSE viewDirection] != VIEW_CUSTOM)
462 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT,
afttstr1));
463 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT,
afttstr2));
464 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT,
afttstr3));
465 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT,
afttstr4));
469 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_INT,
tstr1));
470 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_INT,
tstr2));
471 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_INT,
tstr3));
472 OOGL(glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_INT,
tstr4));
476 GLfloat fanTextures[18] = {
487 OOGL(glTexCoordPointer(2, GL_FLOAT, 0, fanTextures));
489 GLfloat fanColors[36];
490 GLfloat fr = _exhaustBaseColors[0], fg = _exhaustBaseColors[1], fb = _exhaustBaseColors[2];
495 fanColors[i++] = 1.0;
501 fanColors[i++] = 0.5;
503 OOGL(glColorPointer(4, GL_FLOAT, 0, fanColors));
505 OOGL(glDrawElements(GL_TRIANGLE_FAN, 10, GL_UNSIGNED_INT,
tfan1));
507 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
508 OOGL(glDisable(GL_TEXTURE_2D));
510 OOGL(glDisableClientState(GL_COLOR_ARRAY));
519#define PREV(n) ((n + kExhaustFrameCount - 1) % kExhaustFrameCount)
520#define NEXT(n) ((n + 1) % kExhaustFrameCount)
523- (void) saveToLastFrame
532 framePos = HPvector_add(framePos,[ship position]);
535 _track[_nextFrame] = frame;
540- (
Frame) frameAtTime:(
double)t_frame fromFrame:(
Frame) frame_zero
542 if (t_frame >= 0.0)
return frame_zero;
546 int t1 =
PREV(_nextFrame);
547 double moment_in_time = frame_zero.
timeframe + t_frame;
550 if (moment_in_time > _trackTime)
552 frame_one = _track[t1];
553 period = (moment_in_time - t_frame) - _trackTime;
554 f0 = 1.0 + t_frame/period;
556 else if (moment_in_time < _track[_nextFrame].timeframe)
558 return _track[_nextFrame];
562 while (moment_in_time < _track[t1].timeframe)
568 frame_zero = _track[t0];
569 frame_one = _track[t1];
570 period = frame_zero.
timeframe - frame_one.timeframe;
571 f0 = (moment_in_time - _track[t1].timeframe)/period;
575 double f1 = 1.0 - f0;
578 posn.x = f0 * frame_zero.
position.x + f1 * frame_one.position.
x;
579 posn.y = f0 * frame_zero.
position.y + f1 * frame_one.position.
y;
580 posn.z = f0 * frame_zero.
position.z + f1 * frame_one.position.z;
582 qrot.w = (float)f0 * frame_zero.
orientation.w + (float)f1 * frame_one.orientation.w;
583 qrot.x = (float)f0 * frame_zero.
orientation.x + (float)f1 * frame_one.orientation.
x;
584 qrot.y = (float)f0 * frame_zero.
orientation.y + (float)f1 * frame_one.orientation.
y;
585 qrot.z = (float)f0 * frame_zero.
orientation.z + (float)f1 * frame_one.orientation.z;
611 _track[i].timeframe = 0.0;
612 _track[i].position = framePos;
619- (void) rescaleBy:(GLfloat)factor
621 _exhaustScale = vector_multiply_scalar(_exhaustScale, factor);
625- (void) rescaleBy:(GLfloat)factor writeToCache:(BOOL)writeToCache
644 options:kOOTextureMinFilterMipMap | kOOTextureMagFilterLinear | kOOTextureAlphaMask | kOOTextureRepeatT | kOOTextureRepeatS
660+ (void) resetGraphicsState
670@implementation Entity (OOExhaustPlume)
static GLuint afttstr3[4]
static GLuint afttstr2[4]
static GLuint afttstr4[4]
static OOTexture * sPlumeTexture
static GLuint afttstr1[4]
#define OO_ENTER_OPENGL()
HPVector OOHPVectorMultiplyMatrix(HPVector v, OOMatrix m)
void OOGLPushModelView(void)
OOMatrix OOGLPopModelView(void)
@ OPENGL_STATE_ADDITIVE_BLENDING
#define OOVerifyOpenGLState()
#define OOSetOpenGLState(STATE)
Vector vector_forward_from_quaternion(Quaternion quat)
const Quaternion kIdentityQuaternion
Quaternion normalOrientation()
void getRed:green:blue:alpha:(float *red,[green] float *green,[blue] float *blue,[alpha] float *alpha)
OOTexture * plumeTexture()
void registerClient:(id< OOGraphicsResetClient > client)
OOGraphicsResetManager * sharedManager()
id textureWithName:inFolder:options:anisotropy:lodBias:(NSString *name,[inFolder] NSString *directory,[options] OOTextureFlags options,[anisotropy] GLfloat anisotropy,[lodBias] GLfloat lodBias)
OOColor * exhaustEmissiveColor()