LCOV - code coverage report
Current view: top level - Core/Entities - OOExhaustPlumeEntity.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 32 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOExhaustPlumeEntity.m
       4             : 
       5             : 
       6             : Oolite
       7             : Copyright (C) 2004-2013 Giles C Williams and contributors
       8             : 
       9             : This program is free software; you can redistribute it and/or
      10             : modify it under the terms of the GNU General Public License
      11             : as published by the Free Software Foundation; either version 2
      12             : of the License, or (at your option) any later version.
      13             : 
      14             : This program is distributed in the hope that it will be useful,
      15             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             : GNU General Public License for more details.
      18             : 
      19             : You should have received a copy of the GNU General Public License
      20             : along with this program; if not, write to the Free Software
      21             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      22             : MA 02110-1301, USA.
      23             : 
      24             : */
      25             : 
      26             : 
      27             : #import "OOExhaustPlumeEntity.h"
      28             : #import "OOCollectionExtractors.h"
      29             : #import "ShipEntity.h"
      30             : #import "Universe.h"
      31             : #import "OOMacroOpenGL.h"
      32             : #import "PlayerEntity.h"
      33             : #import "MyOpenGLView.h"
      34             : 
      35             : #import "OOTexture.h"
      36             : #import "OOGraphicsResetManager.h"
      37             : 
      38             : 
      39           0 : #define kOverallAlpha           1.0f
      40           0 : #define kTimeStep                       0.05f
      41           0 : #define kFadeLevel1  0.4f
      42           0 : #define kFadeLevel2  0.2f
      43           0 : #define kFadeLevel3  0.02f
      44           0 : #define kScaleLevel1  1.0f
      45           0 : #define kScaleLevel2  0.8f
      46           0 : #define kScaleLevel3  0.6f
      47             : 
      48           0 : static OOTexture *sPlumeTexture = nil;
      49             : 
      50             : 
      51             : @interface OOExhaustPlumeEntity (Private)
      52             : 
      53           0 : - (void) saveToLastFrame;
      54           0 : - (Frame) frameAtTime:(double) t_frame fromFrame:(Frame) frame_zero;    // t_frame is relative to now ie. -0.5 = half a second ago.
      55             : 
      56             : @end
      57             : 
      58             : 
      59             : @implementation OOExhaustPlumeEntity
      60             : 
      61             : + (id) exhaustForShip:(ShipEntity *)ship withDefinition:(NSArray *)definition andScale:(float)scale
      62             : {
      63             :         return [[[self alloc] initForShip:ship withDefinition:definition andScale:(float)scale] autorelease];
      64             : }
      65             : 
      66             : 
      67             : - (id) initForShip:(ShipEntity *)ship withDefinition:(NSArray *)definition andScale:(float)scaleFactor
      68             : {
      69             :         if ([definition count] == 0)
      70             :         {
      71             :                 [self release];
      72             :                 return nil;
      73             :         }
      74             :         
      75             :         if ((self = [super init]))
      76             :         {
      77             :                 [self setOwner:ship];
      78             :                 HPVector pos = { [definition oo_floatAtIndex:0]*scaleFactor, [definition oo_floatAtIndex:1]*scaleFactor, [definition oo_floatAtIndex:2]*scaleFactor };
      79             :                 [self setPosition:pos];
      80             :                 // scale.z is special and *not* multiplied by scaleFactor
      81             :                 Vector scale = { [definition oo_floatAtIndex:3]*scaleFactor, [definition oo_floatAtIndex:4]*scaleFactor, [definition oo_floatAtIndex:5] };
      82             :                 [self setScale:scale];
      83             :         }
      84             :         
      85             :         return self;
      86             : }
      87             : 
      88             : 
      89             : - (Vector) scale
      90             : {
      91             :         return _exhaustScale;
      92             : }
      93             : 
      94             : 
      95             : - (void) setScale:(Vector)scale
      96             : {
      97             :         _exhaustScale = scale;
      98             :         if (scale.z < 0.5 || scale.z > 2.0)
      99             :         {
     100             :                 _exhaustScale.z = 1.0;
     101             :         }
     102             : }
     103             : 
     104             : 
     105           0 : - (BOOL)isExhaust
     106             : {
     107             :         return YES;
     108             : }
     109             : 
     110             : 
     111           0 : - (double)findCollisionRadius
     112             : {
     113             :         return collision_radius;
     114             : }
     115             : 
     116             : 
     117           0 : - (void) update:(OOTimeDelta) delta_t
     118             : {
     119             : // Profiling: this function and subfunctions are expensive - CIM
     120             : 
     121             :         // don't draw if there's no ship, or if we're just jumping out of witchspace/docked at a station!
     122             :         ShipEntity  *ship = [self owner];
     123             : // also don't draw if the ship isn't visible
     124             :         if (EXPECT_NOT(ship == nil || ![ship isVisible] || ([ship isPlayer] && [ship suppressFlightNotifications]))) return;
     125             : 
     126             :         OOTimeAbsolute now = [UNIVERSE getTime];
     127             :         if ([UNIVERSE getTime] > _trackTime + kTimeStep)
     128             :         {
     129             :                 [self saveToLastFrame];
     130             :                 _trackTime = now;
     131             :         }
     132             : 
     133             :         //GLfloat ex_emissive[4]        = {0.7f, 0.9, 1.0f, 0.9f * kOverallAlpha};   // pale blue - old definition
     134             :         collision_radius = 0;
     135             :         GLfloat length;
     136             :         HPVector vertex;
     137             :         GLfloat ex_emissive[4];
     138             :         [[ship exhaustEmissiveColor] getRed:&ex_emissive[0] green:&ex_emissive[1] blue:&ex_emissive[2] alpha:&ex_emissive[3]];
     139             :         const GLfloat s1[8] = { 0.0, M_SQRT1_2, 1.0, M_SQRT1_2, 0.0, -M_SQRT1_2, -1.0, -M_SQRT1_2};
     140             :         const GLfloat c1[8] = { 1.0, M_SQRT1_2, 0.0, -M_SQRT1_2, -1.0, -M_SQRT1_2, 0.0, M_SQRT1_2};
     141             :         
     142             :         Quaternion shipQrotation = [ship normalOrientation];
     143             :         
     144             :         Frame zero =
     145             :         {
     146             :                 .timeframe = [UNIVERSE getTime],
     147             :                 .orientation = shipQrotation,
     148             :                 .k = [ship forwardVector]
     149             :         };
     150             :         int dam = [ship damage];
     151             : 
     152             :         GLfloat speed = [ship speedFactor];
     153             :         // don't draw if not moving.
     154             :         if (EXPECT_NOT(speed <= 0.001f)) return;
     155             :         
     156             :         GLfloat hyper_fade = 8.0f / (8.0f + speed * speed * speed);
     157             :         
     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;      // random fluctuations
     160             :         GLfloat green_factor = speed * ex_emissive[1] * hyper_fade;
     161             :         
     162             :         if (speed > 1.0f)    // afterburner!
     163             :         {
     164             :                 red_factor = 1.5;
     165             :         }
     166             :         
     167             :         if ((int)(ranrot_rand() % 50) < dam - 50)   // flicker the damaged engines
     168             :                 red_factor = 0.0;
     169             :         if ((int)(ranrot_rand() % 40) < dam - 60)
     170             :                 green_factor = 0.0;
     171             :         if ((int)(ranrot_rand() % 25) < dam - 75)
     172             :                 flare_factor = 0.0;
     173             :         
     174             :         HPVector currentPos = ship->position;
     175             :         Vector vfwd = [ship forwardVector];
     176             :         GLfloat spd = 0.5f * [ship flightSpeed];
     177             :         vfwd = vector_multiply_scalar(vfwd, spd);
     178             :         Vector master_i = [ship rightVector];
     179             :         Vector vi,vj,vk;
     180             :         vi = master_i;
     181             :         vj = [ship upVector];
     182             :         vk = [ship forwardVector];
     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);
     186             :         
     187             :         GLfloat speedScale = fminf(1.0f,speed * 5.0f);
     188             : 
     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;  // factor for trail
     196             :         GLfloat q03 = i03/i10;
     197             :         GLfloat q06 = i06/i10;
     198             :         GLfloat q08 = i08/i10;
     199             :         GLfloat r01 = 1.0f - q01;       // factor for jet
     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];
     212             :         
     213             :         int ci = 0;
     214             :         int iv = 0;
     215             :         int i;
     216             :         float r1;
     217             : 
     218             : //      f01.position = vector_subtract(zero.position, vk); // 1m out from zero
     219             :         f01.position = zero.position;
     220             : 
     221             :         ex_emissive[3] = flare_factor * kOverallAlpha;  // fade alpha towards rear of exhaust
     222             :         ex_emissive[1] = green_factor;  // diminish green part towards rear of exhaust
     223             :         ex_emissive[0] = red_factor;            // diminish red part towards rear of exhaust
     224             :         vertex = HPvector_add(f01.position, vectorToHPVector(b01));
     225             :         collision_radius = HPmagnitude(HPvector_subtract(vertex, currentPos));
     226             :         _vertices[iv++] = vertex.x;// + zero.k.x * flare_factor * 4.0;
     227             :         _vertices[iv++] = vertex.y;// + zero.k.y * flare_factor * 4.0;
     228             :         _vertices[iv++] = vertex.z;// + zero.k.z * flare_factor * 4.0;
     229             :         _exhaustBaseColors[ci++] = ex_emissive[0];
     230             :         _exhaustBaseColors[ci++] = ex_emissive[1];
     231             :         _exhaustBaseColors[ci++] = ex_emissive[2];
     232             :         _exhaustBaseColors[ci++] = ex_emissive[3];
     233             : 
     234             : 
     235             :         Vector k1 = f01.k;
     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);
     239             : 
     240             :         for (i = 0; i < 8; i++)
     241             :         {
     242             :                 vertex = HPvector_add(f01.position,
     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)
     248             :                 {
     249             :                         collision_radius = length;
     250             :                 }
     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];
     258             :         }
     259             : 
     260             :         ex_emissive[3] = kFadeLevel1 * flare_factor * kOverallAlpha;    // fade alpha towards rear of exhaust
     261             :         ex_emissive[1] = kFadeLevel1 * green_factor;    // diminish green part towards rear of exhaust
     262             :         ex_emissive[0] = kFadeLevel1 * red_factor;              // diminish red part towards rear of exhaust
     263             : 
     264             :         k1 = f03.k;
     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++)
     268             :         {
     269             :                 r1 = randf();
     270             :                 vertex = HPvector_add(f03.position,
     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)
     277             :                 {
     278             :                         collision_radius = length;
     279             :                 }
     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];
     287             :         }
     288             :         
     289             :         ex_emissive[3] = kFadeLevel2 * flare_factor * kOverallAlpha;    // fade alpha towards rear of exhaust
     290             :         ex_emissive[1] = kFadeLevel2 * green_factor;    // diminish green part towards rear of exhaust
     291             :         ex_emissive[0] = kFadeLevel2 * red_factor;              // diminish red part towards rear of exhaust
     292             : 
     293             :         k1 = f06.k;
     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++)
     297             :         {
     298             :                 r1 = randf();
     299             :                 vertex = HPvector_add(f06.position,
     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)
     306             :                 {
     307             :                         collision_radius = length;
     308             :                 }
     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];
     316             :         }
     317             :         
     318             :         ex_emissive[3] = kFadeLevel3 * flare_factor * kOverallAlpha;    // fade alpha towards rear of exhaust
     319             :         ex_emissive[1] = kFadeLevel3 * green_factor;    // diminish green part towards rear of exhaust
     320             :         ex_emissive[0] = kFadeLevel3 * red_factor;              // diminish red part towards rear of exhaust
     321             :         k1 = f08.k;
     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++)
     325             :         {
     326             :                 r1 = randf();
     327             :                 vertex = HPvector_add(f08.position,
     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)
     334             :                 {
     335             :                         collision_radius = length;
     336             :                 }
     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];
     344             :         }
     345             :         
     346             :         ex_emissive[3] = 0.0;   // fade alpha towards rear of exhaust
     347             :         ex_emissive[1] = 0.0;   // diminish green part towards rear of exhaust
     348             :         ex_emissive[0] = 0.0;   // diminish red part towards rear of exhaust
     349             :         length = HPmagnitude(HPvector_subtract(vertex, currentPos));
     350             :         if (length > collision_radius)
     351             :         {
     352             :                 collision_radius = length;
     353             :         }
     354             :         _vertices[iv++] = f10.position.x;
     355             :         _vertices[iv++] = f10.position.y;
     356             :         _vertices[iv++] = f10.position.z;
     357             :         _exhaustBaseColors[ci++] = ex_emissive[0];
     358             :         _exhaustBaseColors[ci++] = ex_emissive[1];
     359             :         _exhaustBaseColors[ci++] = ex_emissive[2];
     360             :         _exhaustBaseColors[ci++] = ex_emissive[3];
     361             :         
     362             :         (void)iv; (void)ci;     // Suppress Clang static analyzer warnings.
     363             : }
     364             : 
     365           0 : static GLuint tfan1[10] =    {  0,      1,      2,      3,      4,      5,      6,      7,      8,      1 };            // initial fan 0..9
     366             : 
     367             : // normal polys
     368           0 : static GLuint tstr1[9] = {  1, 5, 9, 13, 17, 21, 25, 29, 33 };
     369           0 : static GLuint tstr2[9] = {  2, 6, 10, 14, 18, 22, 26, 30, 33 };
     370           0 : static GLuint tstr3[9] = {  3, 7, 11, 15, 19, 23, 27, 31, 33 };
     371           0 : static GLuint tstr4[9] = {  4, 8, 12, 16, 20, 24, 28, 32, 33 };
     372             : 
     373             : // aft-view special polys
     374           0 : static GLuint afttstr1[4] = {  1, 5, 25, 29 };
     375           0 : static GLuint afttstr2[4] = {  2, 6, 26, 30 };
     376           0 : static GLuint afttstr3[4] = {  3, 7, 27, 31 };
     377           0 : static GLuint afttstr4[4] = {  4, 8, 28, 32 };
     378             : 
     379             : 
     380           0 : static GLfloat pA[6] = { 0.01, 0.0, 2.0, 4.0, 6.0, 10.0 }; // phase adjustments
     381             : 
     382             : 
     383           0 : - (void) drawSubEntityImmediate:(bool)immediate translucent:(bool)translucent
     384             : {
     385             :         if (!translucent)  return;
     386             :         
     387             :         ShipEntity *ship = [self owner];
     388             :         if ([ship speedFactor] <= 0.001f)  return;   // don't draw if not moving according to 'update' calculation
     389             : 
     390             :         OO_ENTER_OPENGL();
     391             :         OOSetOpenGLState(OPENGL_STATE_ADDITIVE_BLENDING);
     392             :         
     393             :         OOGLPopModelView();
     394             :         OOGLPushModelView();
     395             : //      GLTranslateOOVector(vector_flip([self cameraRelativePosition]));
     396             :         HPVector cam = [PLAYER viewpointPosition];
     397             :         for (unsigned n=0;n<34*3;n++)
     398             :         {
     399             :                 switch (n%3) 
     400             :                 {
     401             :                 case 0: // x coordinates
     402             :                         _glVertices[n] = (GLfloat)(_vertices[n] - cam.x);
     403             :                         break;
     404             :                 case 1: // y coordinates
     405             :                         _glVertices[n] = (GLfloat)(_vertices[n] - cam.y);
     406             :                         break;
     407             :                 case 2: // z coordinates
     408             :                         _glVertices[n] = (GLfloat)(_vertices[n] - cam.z);
     409             :                         break;
     410             :                 }
     411             :         }
     412             :         
     413             :         OOGL(glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT));
     414             :         
     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];
     421             : 
     422             : //      OOGL(glDisable(GL_CULL_FACE));          // face culling
     423             :         OOGL(glShadeModel(GL_SMOOTH));
     424             :         
     425             :         OOGL(glEnableClientState(GL_COLOR_ARRAY));
     426             :         OOGL(glVertexPointer(3, GL_FLOAT, 0, _glVertices));
     427             :         OOGL(glColorPointer(4, GL_FLOAT, 0, _exhaustBaseColors));
     428             : 
     429             :         double intpart, dphase = 1.0-modf((double)[UNIVERSE getTime]*2.5,&intpart);
     430             :         GLfloat phase = (GLfloat)dphase;
     431             : 
     432             :         GLfloat texCoords[68] = {
     433             :                 0.5, phase+pA[0],
     434             : 
     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],
     439             : 
     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],
     444             : 
     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],
     449             : 
     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],
     454             : 
     455             :                 0.5, phase+pA[5],
     456             :         };
     457             :         OOGL(glTexCoordPointer(2, GL_FLOAT, 0, texCoords));
     458             : 
     459             :         // reduced detail for internal view to avoid rendering artefacts
     460             :         if ([[self owner] isPlayer] && [UNIVERSE viewDirection] != VIEW_CUSTOM)
     461             :         {
     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));
     466             :         } 
     467             :         else
     468             :         {
     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));
     473             :         }
     474             : 
     475             :         /* Need a different texture and color array for this segment */
     476             :         GLfloat fanTextures[18] = {
     477             :                 0.5f, 0.0f+phase,
     478             :                 0.2f, 0.0f+phase,
     479             :                 0.2f, 0.1f+phase,
     480             :                 0.2f, 0.2f+phase,
     481             :                 0.2f, 0.3f+phase,
     482             :                 0.2f, 0.4f+phase,
     483             :                 0.2f, 0.3f+phase,
     484             :                 0.2f, 0.2f+phase,
     485             :                 0.2f, 0.1f+phase
     486             :         };
     487             :         OOGL(glTexCoordPointer(2, GL_FLOAT, 0, fanTextures));
     488             :         
     489             :         GLfloat fanColors[36];
     490             :         GLfloat fr = _exhaustBaseColors[0], fg = _exhaustBaseColors[1], fb = _exhaustBaseColors[2];
     491             :         unsigned i = 0;
     492             :         fanColors[i++] = fr;
     493             :         fanColors[i++] = fg;
     494             :         fanColors[i++] = fb;
     495             :         fanColors[i++] = 1.0;
     496             :         for (;i<36;)
     497             :         {
     498             :                 fanColors[i++] = fr;
     499             :                 fanColors[i++] = fg;
     500             :                 fanColors[i++] = fb;
     501             :                 fanColors[i++] = 0.5;
     502             :         }
     503             :         OOGL(glColorPointer(4, GL_FLOAT, 0, fanColors));
     504             : 
     505             :         OOGL(glDrawElements(GL_TRIANGLE_FAN, 10, GL_UNSIGNED_INT, tfan1));
     506             : 
     507             :         OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
     508             :         OOGL(glDisable(GL_TEXTURE_2D));
     509             : 
     510             :         OOGL(glDisableClientState(GL_COLOR_ARRAY));
     511             :         
     512             : 
     513             :         OOGL(glPopAttrib());
     514             :         
     515             :         OOVerifyOpenGLState();
     516             : }
     517             : 
     518             : 
     519           0 : #define PREV(n) ((n + kExhaustFrameCount - 1) % kExhaustFrameCount)
     520           0 : #define NEXT(n) ((n + 1) % kExhaustFrameCount)
     521             : 
     522             : 
     523           0 : - (void) saveToLastFrame
     524             : {
     525             :         ShipEntity *ship = [self owner];
     526             :         
     527             :         // Absolute position of self
     528             :         // normally this would use the transformation matrix, but that
     529             :         // introduces inaccuracies
     530             :         // so just use the rotation matrix, then translate using HPVectors
     531             :         HPVector framePos = OOHPVectorMultiplyMatrix([self position], [ship drawRotationMatrix]);
     532             :         framePos = HPvector_add(framePos,[ship position]);
     533             :         Frame frame = { [UNIVERSE getTime], framePos, [ship normalOrientation], [ship upVector] };
     534             :         
     535             :         _track[_nextFrame] = frame;
     536             :         _nextFrame = (_nextFrame + 1) % kExhaustFrameCount;
     537             : }
     538             : 
     539             : 
     540           0 : - (Frame) frameAtTime:(double)t_frame fromFrame:(Frame) frame_zero      // t_frame is relative to now ie. -0.5 = half a second ago.
     541             : {
     542             :         if (t_frame >= 0.0)  return frame_zero;
     543             :         
     544             :         Frame frame_one;
     545             :         
     546             :         int t1 = PREV(_nextFrame);
     547             :         double moment_in_time = frame_zero.timeframe + t_frame;
     548             :         double period, f0;
     549             :         
     550             :         if (moment_in_time > _trackTime)                                     // between the last saved frame and now
     551             :         {
     552             :                 frame_one = _track[t1]; // last saved moment
     553             :                 period = (moment_in_time - t_frame) - _trackTime;
     554             :                 f0 = 1.0 + t_frame/period;
     555             :         }
     556             :         else if (moment_in_time < _track[_nextFrame].timeframe)      // more than kExhaustFrameCount frames back
     557             :         {
     558             :                 return _track[_nextFrame];
     559             :         }
     560             :         else
     561             :         {
     562             :                 while (moment_in_time < _track[t1].timeframe)
     563             :                 {
     564             :                         t1 = PREV(t1);
     565             :                 }
     566             :                 int t0 = NEXT(t1);
     567             :                 
     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;
     572             :         }
     573             :         
     574             :         // interpolate
     575             :         double f1 = 1.0 - f0;
     576             :         
     577             :         HPVector posn;
     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;
     581             :         Quaternion qrot;
     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;
     586             :         
     587             :         Frame result;
     588             :         result.position = posn;
     589             :         result.orientation = qrot;
     590             :         result.timeframe = moment_in_time;
     591             :         result.k = vector_forward_from_quaternion(qrot);
     592             :         return result;
     593             : }
     594             : 
     595             : 
     596             : - (void) resetPlume
     597             : {
     598             :         /*ShipEntity *ship = [self owner];
     599             :         
     600             :         // Absolute position of self
     601             :         Vector framePos = OOVectorMultiplyMatrix([self position], [ship drawTransformationMatrix]);
     602             :         Frame frame = { [UNIVERSE getTime], framePos, [ship normalOrientation], [ship upVector] };
     603             :         
     604             :         _track[_nextFrame] = frame;
     605             :         _nextFrame = (_nextFrame + 1) % kExhaustFrameCount;*/
     606             :         _nextFrame = 0;
     607             :         HPVector framePos = OOHPVectorMultiplyMatrix([self position], [[self owner] drawTransformationMatrix]);
     608             :         uint8_t i;
     609             :         for (i = 0; i < kExhaustFrameCount; i++)
     610             :         {
     611             :                 _track[i].timeframe = 0.0;
     612             :                 _track[i].position = framePos;
     613             :                 _track[i].orientation = kIdentityQuaternion;
     614             :                 _track[i].k = kZeroVector;
     615             :         }
     616             : }
     617             : 
     618             : 
     619           0 : - (void) rescaleBy:(GLfloat)factor
     620             : {
     621             :         _exhaustScale = vector_multiply_scalar(_exhaustScale, factor);
     622             : }
     623             : 
     624             : 
     625           0 : - (void) rescaleBy:(GLfloat)factor writeToCache:(BOOL)writeToCache
     626             : {
     627             :         /* Do nothing; this is only needed because of OOEntityWithDrawable
     628             :            implementation requirements */
     629             : }
     630             : 
     631             : 
     632             : - (OOTexture *) texture
     633             : {
     634             :         return [OOExhaustPlumeEntity plumeTexture];
     635             : }
     636             : 
     637             : 
     638             : + (void) setUpTexture
     639             : {
     640             :         if (sPlumeTexture == nil)
     641             :         {
     642             :                 sPlumeTexture = [[OOTexture textureWithName:@"oolite-exhaust-blur.png"
     643             :                                                                                   inFolder:@"Textures"
     644             :                                                                                    options:kOOTextureMinFilterMipMap | kOOTextureMagFilterLinear | kOOTextureAlphaMask | kOOTextureRepeatT | kOOTextureRepeatS
     645             :                                                                                 anisotropy:kOOTextureDefaultAnisotropy / 2.0
     646             :                                                                                    lodBias:0.0] retain];
     647             :                 [[OOGraphicsResetManager sharedManager] registerClient:(id<OOGraphicsResetClient>)[OOExhaustPlumeEntity class]];
     648             : 
     649             :         }
     650             : }
     651             : 
     652             : 
     653             : + (OOTexture *) plumeTexture
     654             : {
     655             :         if (sPlumeTexture == nil)  [self setUpTexture];
     656             :         return sPlumeTexture;
     657             : }
     658             : 
     659             : 
     660             : + (void) resetGraphicsState
     661             : {
     662             :         [sPlumeTexture release];
     663             :         sPlumeTexture = nil;
     664             : }
     665             : 
     666             : 
     667             : @end
     668             : 
     669             : 
     670             : @implementation Entity (OOExhaustPlume)
     671             : 
     672             : - (BOOL)isExhaust
     673             : {
     674             :         return NO;
     675             : }
     676             : 
     677             : @end

Generated by: LCOV version 1.14