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

          Line data    Source code
       1           0 : /*
       2             :  
       3             :  OOPlanetDrawable.m
       4             :  
       5             :  Oolite
       6             :  Copyright (C) 2004-2013 Giles C Williams and contributors
       7             :  
       8             :  This program is free software; you can redistribute it and/or
       9             :  modify it under the terms of the GNU General Public License
      10             :  as published by the Free Software Foundation; either version 2
      11             :  of the License, or (at your option) any later version.
      12             :  
      13             :  This program is distributed in the hope that it will be useful,
      14             :  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  GNU General Public License for more details.
      17             :  
      18             :  You should have received a copy of the GNU General Public License
      19             :  along with this program; if not, write to the Free Software
      20             :  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      21             :  MA 02110-1301, USA.
      22             :  
      23             :  */
      24             : 
      25             : #import "OOStellarBody.h"
      26             : #if NEW_PLANETS
      27             : 
      28             : 
      29             : #import "OOPlanetDrawable.h"
      30             : #import "OOPlanetData.h"
      31             : #import "OOSingleTextureMaterial.h"
      32             : #import "OOOpenGL.h"
      33             : #import "OOMacroOpenGL.h"
      34             : #import "Universe.h"
      35             : #import "MyOpenGLView.h"
      36             : 
      37             : #ifndef NDEBUG
      38             : #import "Entity.h"
      39             : #import "OODebugGLDrawing.h"
      40             : #import "OODebugFlags.h"
      41             : #endif
      42             : 
      43             : 
      44             : #define LOD_GRANULARITY         ((float)(kOOPlanetDataLevels - 1))
      45             : #define LOD_FACTOR                      (1.0 / 4.0)
      46             : 
      47             : 
      48             : @interface OOPlanetDrawable (Private)
      49             : 
      50             : - (void) recalculateTransform;
      51             : 
      52             : - (void) debugDrawNormals;
      53             : 
      54             : - (void) renderCommonParts;
      55             : 
      56             : @end
      57             : 
      58             : 
      59             : @implementation OOPlanetDrawable
      60             : 
      61             : + (instancetype) planetWithTextureName:(NSString *)textureName radius:(float)radius
      62             : {
      63             :         OOPlanetDrawable *result = [[[self alloc] init] autorelease];
      64             :         [result setTextureName:textureName];
      65             :         [result setRadius:radius];
      66             :         
      67             :         return result;
      68             : }
      69             : 
      70             : 
      71             : + (instancetype) atmosphereWithRadius:(float)radius
      72             : {
      73             :         OOPlanetDrawable *result = [[[self alloc] initAsAtmosphere] autorelease];
      74             :         [result setRadius:radius];
      75             :         
      76             :         return result;
      77             : }
      78             : 
      79             : 
      80             : - (id) init
      81             : {
      82             :         if ((self = [super init]))
      83             :         {
      84             :                 _radius = 1.0f;
      85             :                 [self recalculateTransform];
      86             :                 [self setLevelOfDetail:0.5f];
      87             :         }
      88             :         
      89             :         return self;
      90             : }
      91             : 
      92             : 
      93             : - (id) initAsAtmosphere
      94             : {
      95             :         if ((self = [self init]))
      96             :         {
      97             :                 _isAtmosphere = YES;
      98             :         }
      99             :         
     100             :         return self;
     101             : }
     102             : 
     103             : 
     104             : - (void) dealloc
     105             : {
     106             :         DESTROY(_material);
     107             :         
     108             :         [super dealloc];
     109             : }
     110             : 
     111             : 
     112             : - (id) copyWithZone:(NSZone *)zone
     113             : {
     114             :         OOPlanetDrawable *copy = [[[self class] allocWithZone:zone] init];
     115             :         [copy setMaterial:[self material]];
     116             :         copy->_isAtmosphere = _isAtmosphere;
     117             :         copy->_radius = _radius;
     118             :         copy->_transform = _transform;
     119             :         copy->_lod = _lod;
     120             :         
     121             :         return copy;
     122             : }
     123             : 
     124             : 
     125             : - (OOMaterial *) material
     126             : {
     127             :         return _material;
     128             : }
     129             : 
     130             : 
     131             : - (void) setMaterial:(OOMaterial *)material
     132             : {
     133             :         [_material autorelease];
     134             :         _material = [material retain];
     135             : }
     136             : 
     137             : 
     138             : - (NSString *) textureName
     139             : {
     140             :         return [_material name];
     141             : }
     142             : 
     143             : 
     144             : - (void) setTextureName:(NSString *)textureName
     145             : {
     146             :         if (![textureName isEqual:[self textureName]])
     147             :         {
     148             :                 [_material release];
     149             :                 NSDictionary *spec = [@"{diffuse_map={repeat_s=yes;cube_map=yes};}" propertyList];
     150             :                 _material = [[OOSingleTextureMaterial alloc] initWithName:textureName configuration:spec];
     151             :         }
     152             : }
     153             : 
     154             : 
     155             : - (float) radius
     156             : {
     157             :         return _radius;
     158             : }
     159             : 
     160             : 
     161             : - (void) setRadius:(float)radius
     162             : {
     163             :         _radius = fabsf(radius);
     164             :         [self recalculateTransform];
     165             : }
     166             : 
     167             : 
     168             : - (float) levelOfDetail
     169             : {
     170             :         return (float)_lod / LOD_GRANULARITY;
     171             : }
     172             : 
     173             : 
     174             : - (void) setLevelOfDetail:(float)lod
     175             : {
     176             :         _lod = roundf(OOClamp_0_1_f(lod) * LOD_GRANULARITY);
     177             : }
     178             : 
     179             : 
     180             : - (void) calculateLevelOfDetailForViewDistance:(float)distance
     181             : {
     182             :         BOOL simple = [UNIVERSE reducedDetail];
     183             :         float   drawFactor = [[UNIVERSE gameView] viewSize].width / (simple ? 100.0 : 40.0);
     184             :         float   drawRatio2 = drawFactor * _radius / sqrtf(distance); // proportional to size on screen in pixels
     185             :         
     186             :         float lod = sqrtf(drawRatio2 * LOD_FACTOR);
     187             :         if (simple)
     188             :         {
     189             :                 lod -= 0.5f / LOD_GRANULARITY;  // Make LOD transitions earlier.
     190             :                 lod = OOClamp_0_max_f(lod, (LOD_GRANULARITY - 1) / LOD_GRANULARITY);    // Don't use highest LOD.
     191             :         }
     192             :         [self setLevelOfDetail:lod];
     193             : }
     194             : 
     195             : 
     196             : - (void) renderOpaqueParts
     197             : {
     198             :         assert(_lod < kOOPlanetDataLevels);
     199             : 
     200             :         OOSetOpenGLState(OPENGL_STATE_OPAQUE);
     201             :         
     202             :         [self renderCommonParts];
     203             : 
     204             :         OOVerifyOpenGLState();
     205             : 
     206             : }
     207             : 
     208             : 
     209             : - (void) renderTranslucentParts
     210             : {
     211             :         assert(_lod < kOOPlanetDataLevels);
     212             : 
     213             :         // yes, opaque - necessary changes made later
     214             :         OOSetOpenGLState(OPENGL_STATE_OPAQUE);
     215             :         
     216             :         [self renderCommonParts];
     217             : 
     218             :         OOVerifyOpenGLState();
     219             : 
     220             : }
     221             : 
     222             : 
     223             : - (void) renderTranslucentPartsOnOpaquePass
     224             : {
     225             :         assert(_lod < kOOPlanetDataLevels);
     226             :         
     227             :         OO_ENTER_OPENGL();
     228             : 
     229             :         // yes, opaque - necessary changes made later
     230             :         OOSetOpenGLState(OPENGL_STATE_OPAQUE);
     231             :         
     232             :         OOGL(glDisable(GL_DEPTH_TEST));
     233             :         [self renderCommonParts];
     234             :         OOGL(glEnable(GL_DEPTH_TEST));
     235             : 
     236             :         OOVerifyOpenGLState();
     237             : 
     238             : }
     239             : 
     240             : 
     241             : - (void) renderCommonParts
     242             : {
     243             :         const OOPlanetDataLevel *data = &kPlanetData[_lod];
     244             :         
     245             :         OO_ENTER_OPENGL();
     246             :         
     247             :         OOGL(glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT));
     248             :         OOGL(glShadeModel(GL_SMOOTH));
     249             :         
     250             :         if (_isAtmosphere)
     251             :         {
     252             :                 OOGL(glEnable(GL_BLEND));
     253             :                 OOGL(glDepthMask(GL_FALSE));
     254             :         }
     255             :         else
     256             :         {
     257             :                 OOGL(glDisable(GL_BLEND));
     258             :         }
     259             :         
     260             :         // Scale the ball.
     261             :         OOGLPushModelView();
     262             :         OOGLMultModelView(_transform);
     263             :         
     264             :         [_material apply];
     265             :         
     266             :         OOGL(glEnable(GL_LIGHTING));
     267             :         OOGL(glEnable(GL_TEXTURE_2D));
     268             : 
     269             : #if OO_TEXTURE_CUBE_MAP
     270             :         if ([_material wantsNormalsAsTextureCoordinates])
     271             :         {
     272             :                 OOGL(glDisable(GL_TEXTURE_2D));
     273             :                 OOGL(glEnable(GL_TEXTURE_CUBE_MAP));
     274             :         }
     275             : #endif
     276             :         
     277             :         OOGL(glDisableClientState(GL_COLOR_ARRAY));
     278             :         
     279             :         OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
     280             :         
     281             :         OOGL(glVertexPointer(3, GL_FLOAT, 0, kOOPlanetVertices));
     282             :         if ([_material wantsNormalsAsTextureCoordinates])
     283             :         {
     284             :                 OOGL(glTexCoordPointer(3, GL_FLOAT, 0, kOOPlanetVertices));
     285             :         }
     286             :         else
     287             :         {
     288             :                 OOGL(glTexCoordPointer(2, GL_FLOAT, 0, kOOPlanetTexCoords));
     289             :         }
     290             :         
     291             :         // FIXME: instead of GL_RESCALE_NORMAL, consider copying and transforming the vertex array for each planet.
     292             :         OOGL(glEnable(GL_RESCALE_NORMAL));
     293             :         OOGL(glNormalPointer(GL_FLOAT, 0, kOOPlanetVertices));
     294             :         
     295             :         OOGL(glDrawElements(GL_TRIANGLES, data->faceCount*3, data->type, data->indices));
     296             :         
     297             : #ifndef NDEBUG
     298             :         if ([UNIVERSE wireframeGraphics])
     299             :         {
     300             :                 OODebugDrawBasisAtOrigin(1.5);
     301             :         }
     302             : #endif
     303             : 
     304             : #if OO_TEXTURE_CUBE_MAP
     305             :         if ([_material wantsNormalsAsTextureCoordinates])
     306             :         {
     307             :                 OOGL(glEnable(GL_TEXTURE_2D));
     308             :                 OOGL(glDisable(GL_TEXTURE_CUBE_MAP));
     309             :         }
     310             : #endif
     311             : 
     312             :         
     313             :         OOGLPopModelView();
     314             : #ifndef NDEBUG
     315             :         if (gDebugFlags & DEBUG_DRAW_NORMALS)  [self debugDrawNormals];
     316             : #endif
     317             :         
     318             :         [OOMaterial applyNone];
     319             :         OOGL(glPopAttrib());
     320             :         
     321             :         OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
     322             :         
     323             : }
     324             : 
     325             : 
     326             : - (BOOL) hasOpaqueParts
     327             : {
     328             :         return !_isAtmosphere;
     329             : }
     330             : 
     331             : 
     332             : - (BOOL) hasTranslucentParts
     333             : {
     334             :         return _isAtmosphere;
     335             : }
     336             : 
     337             : 
     338             : - (GLfloat) collisionRadius
     339             : {
     340             :         return _radius;
     341             : }
     342             : 
     343             : 
     344             : - (GLfloat) maxDrawDistance
     345             : {
     346             :         // FIXME
     347             :         return INFINITY;
     348             : }
     349             : 
     350             : 
     351             : - (BoundingBox) boundingBox
     352             : {
     353             :         return (BoundingBox){{ -_radius, -_radius, -_radius }, { _radius, _radius, _radius }};
     354             : }
     355             : 
     356             : 
     357             : - (void) setBindingTarget:(id<OOWeakReferenceSupport>)target
     358             : {
     359             :         [_material setBindingTarget:target];
     360             : }
     361             : 
     362             : 
     363             : - (void) dumpSelfState
     364             : {
     365             :         [super dumpSelfState];
     366             :         OOLog(@"dumpState.planetDrawable", @"radius: %g", [self radius]);
     367             :         OOLog(@"dumpState.planetDrawable", @"LOD: %g", [self levelOfDetail]);
     368             : }
     369             : 
     370             : 
     371             : - (void) recalculateTransform
     372             : {
     373             :         _transform = OOMatrixForScaleUniform(_radius);
     374             : }
     375             : 
     376             : 
     377             : #ifndef NDEBUG
     378             : 
     379             : - (void) debugDrawNormals
     380             : {
     381             :         OODebugWFState          state;
     382             :         
     383             :         OO_ENTER_OPENGL();
     384             :         
     385             :         state = OODebugBeginWireframe(NO);
     386             :         
     387             :         const OOPlanetDataLevel *data = &kPlanetData[_lod];
     388             :         unsigned i;
     389             :         
     390             :         OOGLBEGIN(GL_LINES);
     391             :         for (i = 0; i < data->vertexCount; i++)
     392             :         {
     393             :                 /*      Fun sphere facts: the normalized coordinates of a point on a sphere at the origin
     394             :                         is equal to the object-space normal of the surface at that point.
     395             :                         Furthermore, we can construct the binormal (a vector pointing westward along the
     396             :                         surface) as the cross product of the normal with the Y axis. (This produces
     397             :                         singularities at the pole, but there have to be singularities according to the
     398             :                         Hairy Ball Theorem.) The tangent (a vector north along the surface) is then the
     399             :                         inverse of the cross product of the normal and binormal.
     400             :                         
     401             :                         (This comment courtesy of the in-development planet shader.)
     402             :                 */
     403             :                 Vector v = make_vector(kOOPlanetVertices[i * 3], kOOPlanetVertices[i * 3 + 1], kOOPlanetVertices[i * 3 + 2]);
     404             :                 Vector n = v;
     405             :                 v = OOVectorMultiplyMatrix(v, _transform);
     406             :                 
     407             :                 glColor3f(0.0f, 1.0f, 1.0f);
     408             :                 GLVertexOOVector(v);
     409             :                 GLVertexOOVector(vector_add(v, vector_multiply_scalar(n, _radius * 0.05)));
     410             :                 
     411             :                 Vector b = cross_product(n, kBasisYVector);
     412             :                 Vector t = vector_flip(true_cross_product(n, b));
     413             :                 
     414             :                 glColor3f(1.0f, 1.0f, 0.0f);
     415             :                 GLVertexOOVector(v);
     416             :                 GLVertexOOVector(vector_add(v, vector_multiply_scalar(t, _radius * 0.03)));
     417             :                 
     418             :                 glColor3f(0.0f, 1.0f, 0.0f);
     419             :                 GLVertexOOVector(v);
     420             :                 GLVertexOOVector(vector_add(v, vector_multiply_scalar(b, _radius * 0.03)));
     421             :         }
     422             :         OOGLEND();
     423             :         
     424             :         OODebugEndWireframe(state);
     425             : }
     426             : 
     427             : 
     428             : - (NSSet *) allTextures
     429             : {
     430             :         return [[self material] allTextures];
     431             : }
     432             : 
     433             : #endif
     434             : 
     435             : @end
     436             : 
     437             : #endif  /* NEW_PLANETS */

Generated by: LCOV version 1.14