2005-04-19 19:53:18 +00:00
//
// Entity . m
/ *
*
* Oolite
*
* Created by Giles Williams on Sat Apr 03 2004.
* Copyright ( c ) 2004 for aegidian . org . All rights reserved .
*
Copyright ( c ) 2004 , Giles C Williams
All rights reserved .
This work is licensed under the Creative Commons Attribution - NonCommercial - ShareAlike License .
To view a copy of this license , visit http : // creativecommons . org / licenses / by - nc - sa / 2.0 /
or send a letter to Creative Commons , 559 Nathan Abbott Way , Stanford , California 94305 , USA .
You are free :
• to copy , distribute , display , and perform the work
• to make derivative works
Under the following conditions :
• Attribution . You must give the original author credit .
• Noncommercial . You may not use this work for commercial purposes .
• Share Alike . If you alter , transform , or build upon this work ,
you may distribute the resulting work only under a license identical to this one .
For any reuse or distribution , you must make clear to others the license terms of this work .
Any of these conditions can be waived if you get permission from the copyright holder .
Your fair use and other rights are in no way affected by the above .
* /
# import "Entity.h"
# import "vector.h"
# import "Universe.h"
# import "TextureStore.h"
# import "ResourceManager.h"
// global flag for VAR
BOOL global_usingVAR ;
BOOL global_testForVAR ;
static Universe * data_store _universe ;
@ implementation Entity
// class methods , they set the underlying data_storage universe
+ ( void ) setDataStore : ( Universe * ) univ
{
if ( univ )
data_store _universe = univ ;
// NSLog ( @ "--- Universe for Data Storage set to %@" , univ ) ;
global_usingVAR = NO ;
global_testForVAR = YES ;
}
+ ( Universe * ) dataStore
{
return data_store _universe ;
}
- ( id ) init
{
self = [ super init ] ;
//
quaternion_set _identity ( & q_rotation ) ;
quaternion_into _gl _matrix ( q_rotation , rotMatrix ) ;
//
position = make_vector ( 0.0 , 0.0 , 0.0 ) ;
//
zero_distance = 0.0 ; // 10 km
no_draw _distance = 100000.0 ; // 10 km
//
distance_travelled = 0.0 ;
//
energy = 0.0 ;
//
collision_radius = 0.0 ;
//
collidingEntities = [ [ NSMutableArray alloc ] initWithCapacity : 16 ] ; // alloc automatically retains
//
scan_class = CLASS_NOT _SET ;
//
universal_id = NO_TARGET ;
universe = nil ;
//
is_smooth _shaded = NO ;
//
n_vertices = 0 ;
n_faces = 0 ;
//
displayListName = 0 ;
//
status = STATUS_DEMO ;
//
basefile = @ "No Model" ;
//
throw_sparks = NO ;
//
usingVAR = NO ;
//
2005-05-06 20:13:49 +00:00
isParticle = NO ;
isRing = NO ;
isShip = NO ;
isStation = NO ;
isPlanet = NO ;
isPlayer = NO ;
2005-05-21 08:15:49 +00:00
isSky = NO ;
2005-05-06 20:13:49 +00:00
//
2005-05-23 13:23:51 +00:00
isSunlit = YES ;
shadingEntityID = NO_TARGET ;
//
2005-04-19 19:53:18 +00:00
return self ;
}
- ( void ) dealloc
{
if ( universe ) [ universe release ] ;
if ( basefile ) [ basefile release ] ;
if ( collidingEntities ) [ collidingEntities release ] ;
[ super dealloc ] ;
}
- ( void ) warnAboutHostiles
{
// do nothing for now , this can be expanded in sub classes
NSLog ( @ "***** Entity does nothing in warnAboutHostiles" ) ;
}
- ( Universe * ) universe
{
return universe ;
}
- ( void ) setUniverse : ( Universe * ) univ
{
if ( univ )
{
if ( universe ) [ universe release ] ;
universe = [ univ retain ] ;
}
else
{
if ( universe ) [ universe release ] ;
universe = nil ;
}
}
- ( void ) setUniversal_id : ( int ) uid
{
universal_id = uid ;
}
- ( int ) universal_id
{
return universal_id ;
}
- ( BOOL ) throwingSparks
{
return throw_sparks ;
}
- ( void ) setThrowSparks : ( BOOL ) value
{
throw_sparks = value ;
}
- ( void ) throwSparks ;
{
// do nothing for now
}
- ( BOOL ) isSmoothShaded
{
return is_smooth _shaded ;
}
- ( void ) setSmoothShaded : ( BOOL ) value
{
is_smooth _shaded = value ;
}
- ( void ) setOwner : ( Entity * ) ent
{
int owner_id = [ ent universal_id ] ;
if ( universe )
{
if ( [ universe entityForUniversalID : owner_id ] = = ent ) // check to make sure it ' s kosher
owner = owner_id ;
else
owner = NO_TARGET ;
}
else
{
owner = owner_id ; // if the universe hasn ' t been initialised yet , trust the sender
}
}
- ( Entity * ) owner
{
return [ universe entityForUniversalID : owner ] ;
}
- ( void ) setModel : ( NSString * ) modelName
{
// clear old data
if ( basefile ) [ basefile release ] ;
basefile = [ modelName retain ] ;
//
[ self regenerateDisplayList ] ;
//
[ self loadData : basefile ] ;
//
[ self checkNormalsAndAdjustWinding ] ;
//
// set the collision radius
//
collision_radius = [ self findCollisionRadius ] ;
// NSLog ( @ "Entity with model '%@' collision radius set to %f" , modelName , collision_radius ) ;
//
}
- ( NSString * ) getModel
{
return basefile ;
}
- ( void ) setPosition : ( Vector ) posn
{
position . x = posn . x ;
position . y = posn . y ;
position . z = posn . z ;
}
- ( void ) setPosition : ( GLfloat ) x : ( GLfloat ) y : ( GLfloat ) z
{
position . x = x ;
position . y = y ;
position . z = z ;
}
- ( double ) getZeroDistance
{
// NSLog ( @ "DEBUG %@ %.1f" , self , zero_distance ) ;
return zero_distance ;
}
- ( Vector ) relative_position
{
return relative_position ;
}
- ( NSComparisonResult ) compareZeroDistance : ( Entity * ) otherEntity ;
{
2005-05-06 20:13:49 +00:00
if ( ( otherEntity ) && ( zero_distance > otherEntity -> zero_distance ) )
2005-04-19 19:53:18 +00:00
return NSOrderedAscending ;
else
return NSOrderedDescending ;
}
- ( BoundingBox ) getBoundingBox
{
return boundingBox ;
}
- ( GLfloat ) mass
{
return mass ;
}
- ( void ) setQRotation : ( Quaternion ) quat
{
q_rotation = quat ;
quaternion_into _gl _matrix ( q_rotation , rotMatrix ) ;
}
- ( Quaternion ) QRotation
{
return q_rotation ;
}
- ( void ) setVelocity : ( Vector ) vel
{
velocity = vel ;
}
- ( Vector ) getVelocity
{
return velocity ;
}
- ( double ) getVelocityAsSpeed
{
return sqrt ( velocity . x * velocity . x + velocity . y * velocity . y + velocity . z * velocity . z ) ;
}
- ( double ) distance_travelled
{
return distance_travelled ;
}
- ( void ) setDistanceTravelled : ( double ) value
{
distance_travelled = value ;
}
- ( void ) setStatus : ( int ) stat
{
status = stat ;
}
- ( int ) getStatus
{
return status ;
}
- ( void ) setScanClass : ( int ) s_class
{
scan_class = s_class ;
}
- ( int ) scanClass
{
return scan_class ;
}
- ( void ) setEnergy : ( double ) amount
{
energy = amount ;
}
- ( double ) getEnergy
{
return energy ;
}
- ( void ) applyRoll : ( GLfloat ) roll andClimb : ( GLfloat ) climb
{
2005-05-23 15:14:55 +00:00
if ( ( roll = = 0.0 ) && ( climb = = 0.0 ) && ( ! has_rotated ) )
return ;
if ( roll )
quaternion_rotate _about _z ( & q_rotation , - roll ) ;
if ( climb )
quaternion_rotate _about _x ( & q_rotation , - climb ) ;
2005-04-19 19:53:18 +00:00
quaternion_normalise ( & q_rotation ) ;
quaternion_into _gl _matrix ( q_rotation , rotMatrix ) ;
}
- ( void ) applyRoll : ( GLfloat ) roll climb : ( GLfloat ) climb andYaw : ( GLfloat ) yaw
{
2005-05-23 15:14:55 +00:00
if ( ( roll = = 0.0 ) && ( climb = = 0.0 ) && ( yaw = = 0.0 ) && ( ! has_rotated ) )
return ;
if ( roll )
quaternion_rotate _about _z ( & q_rotation , - roll ) ;
if ( climb )
quaternion_rotate _about _x ( & q_rotation , - climb ) ;
if ( yaw )
quaternion_rotate _about _y ( & q_rotation , - yaw ) ;
2005-04-19 19:53:18 +00:00
quaternion_normalise ( & q_rotation ) ;
quaternion_into _gl _matrix ( q_rotation , rotMatrix ) ;
}
- ( void ) moveForward : ( double ) amount
{
Vector forward = vector_forward _from _quaternion ( q_rotation ) ;
distance_travelled + = amount ;
position . x + = amount * forward . x ;
position . y + = amount * forward . y ;
position . z + = amount * forward . z ;
}
- ( GLfloat * ) rotationMatrix
{
return rotMatrix ;
}
- ( Vector ) getPosition
{
return position ;
}
- ( Vector ) getViewpointPosition
{
return position ;
}
- ( BOOL ) canCollide
{
return YES ;
}
- ( double ) collisionRadius
{
return collision_radius ;
}
- ( void ) setCollisionRadius : ( double ) amount
{
collision_radius = amount ;
}
- ( NSMutableArray * ) collisionArray
{
return collidingEntities ;
}
- ( void ) drawEntity : ( BOOL ) immediate : ( BOOL ) translucent
{
2005-05-21 08:15:49 +00:00
// draw the thing !
2005-04-19 19:53:18 +00:00
//
int ti ;
GLfloat mat_ambient [ ] = { 1.0 , 1.0 , 1.0 , 1.0 } ;
2005-05-06 20:13:49 +00:00
GLfloat mat_no [ ] = { 0.0 , 0.0 , 0.0 , 1.0 } ;
2005-04-19 19:53:18 +00:00
if ( is_smooth _shaded )
glShadeModel ( GL_SMOOTH ) ;
else
glShadeModel ( GL_FLAT ) ;
2005-05-21 08:15:49 +00:00
2005-04-19 19:53:18 +00:00
if ( ! translucent )
{
if ( basefile )
{
2005-04-30 20:39:13 +00:00
// calls moved here because they are unsupported in display lists
//
glDisableClientState ( GL_COLOR _ARRAY ) ;
glDisableClientState ( GL_INDEX _ARRAY ) ;
glDisableClientState ( GL_EDGE _FLAG _ARRAY ) ;
//
glEnableClientState ( GL_VERTEX _ARRAY ) ;
2005-05-21 08:15:49 +00:00
glEnableClientState ( GL_NORMAL _ARRAY ) ;
2005-04-30 20:39:13 +00:00
glEnableClientState ( GL_TEXTURE _COORD _ARRAY ) ;
2005-05-21 08:15:49 +00:00
2005-04-30 20:39:13 +00:00
glVertexPointer ( 3 , GL_FLOAT , 0 , entityData . vertex_array ) ;
glNormalPointer ( GL_FLOAT , 0 , entityData . normal_array ) ;
glTexCoordPointer ( 2 , GL_FLOAT , 0 , entityData . texture_uv _array ) ;
2005-05-21 08:15:49 +00:00
2005-04-19 19:53:18 +00:00
if ( immediate )
{
# ifdef GNUSTEP
// TODO : Find out what these APPLE functions can be replaced with
# else
if ( usingVAR )
glBindVertexArrayAPPLE ( gVertexArrayRangeObjects [ 0 ] ) ;
# endif
2005-04-30 20:39:13 +00:00
2005-04-19 19:53:18 +00:00
//
2005-04-30 20:39:13 +00:00
// gap removal ( draws flat polys )
2005-04-19 19:53:18 +00:00
//
2005-05-21 08:15:49 +00:00
glDisable ( GL_TEXTURE _2D ) ;
2005-04-19 19:53:18 +00:00
GLfloat amb_diff0 [ ] = { 0.5 , 0.5 , 0.5 , 1.0 } ;
glMaterialfv ( GL_FRONT _AND _BACK , GL_AMBIENT _AND _DIFFUSE , amb_diff0 ) ;
2005-04-30 20:39:13 +00:00
glMaterialfv ( GL_FRONT _AND _BACK , GL_EMISSION , mat_no ) ;
2005-04-19 19:53:18 +00:00
glColor4f ( 0.25 , 0.25 , 0.25 , 1.0 ) ; // gray
2005-04-30 20:39:13 +00:00
glDepthMask ( GL_FALSE ) ; // don ' t write to depth buffer
glDrawArrays ( GL_TRIANGLES , 0 , entityData . n_triangles ) ; // draw in gray to mask the edges
2005-04-19 19:53:18 +00:00
glDepthMask ( GL_TRUE ) ;
//
// now the textures . . .
//
glEnable ( GL_TEXTURE _2D ) ;
glTexEnvf ( GL_TEXTURE _ENV , GL_TEXTURE _ENV _MODE , GL_MODULATE ) ;
2005-04-30 20:39:13 +00:00
glMaterialfv ( GL_FRONT _AND _BACK , GL_AMBIENT _AND _DIFFUSE , mat_ambient ) ;
glMaterialfv ( GL_FRONT _AND _BACK , GL_EMISSION , mat_no ) ;
2005-05-21 08:15:49 +00:00
2005-04-19 19:53:18 +00:00
for ( ti = 1 ; ti <= n_textures ; ti + + )
{
glBindTexture ( GL_TEXTURE _2D , texture_name [ ti ] ) ;
glDrawArrays ( GL_TRIANGLES , triangle_range [ ti ] . location , triangle_range [ ti ] . length ) ;
}
}
else
{
if ( displayListName ! = 0 )
2005-05-21 08:15:49 +00:00
{
2005-04-19 19:53:18 +00:00
glCallList ( displayListName ) ;
2005-05-21 08:15:49 +00:00
}
2005-04-19 19:53:18 +00:00
else
{
[ self initialiseTextures ] ;
[ self generateDisplayList ] ;
}
}
}
else
{
NSLog ( @ "ERROR no basefile for entity %@" ) ;
NSBeep ( ) ;
}
}
glShadeModel ( GL_SMOOTH ) ;
2005-05-21 08:15:49 +00:00
checkGLErrors ( [ NSString stringWithFormat : @ "Entity after drawing %@" , self ] ) ;
2005-04-19 19:53:18 +00:00
}
- ( void ) drawSubEntity : ( BOOL ) immediate : ( BOOL ) translucent
{
2005-05-06 20:13:49 +00:00
Entity * my_owner = [ universe entityForUniversalID : owner ] ;
if ( my_owner )
2005-04-19 19:53:18 +00:00
{
// this test provides an opportunity to do simple LoD culling
//
2005-05-06 20:13:49 +00:00
zero_distance = my_owner -> zero_distance ;
2005-04-19 19:53:18 +00:00
if ( zero_distance > no_draw _distance )
{
// NSLog ( @ "DEBUG - sub entity '%@' too far away to draw" , self ) ;
return ; // TOO FAR AWAY
}
}
if ( status ! = STATUS_ACTIVE )
{
if ( ( ! [ universe reducedDetail ] ) || ( status = = STATUS_EFFECT ) ) // don ' t draw passive subentities except exhausts in reduced detail mode .
{
glPushMatrix ( ) ;
// position and orientation is relative to owner
// NSLog ( @ "DEBUG drawing passive subentity at %.3f, %.3f, %.3f" , position . x , position . y , position . z ) ;
glTranslated ( position . x , position . y , position . z ) ;
glMultMatrixf ( rotMatrix ) ;
[ self drawEntity : immediate : translucent ] ;
glPopMatrix ( ) ;
// NSLog ( @ "drawn static entity : %@" , basefile ) ;
}
}
else
{
2005-05-06 20:13:49 +00:00
Vector abspos = position ; // STATUS_ACTIVE means it is in control of it ' s own orientation
Entity * father = my_owner ;
2005-04-19 19:53:18 +00:00
GLfloat * r_mat = [ father rotationMatrix ] ;
while ( father )
{
mult_vector _gl _matrix ( & abspos , r_mat ) ;
2005-05-06 20:13:49 +00:00
Vector pos = father -> position ;
2005-04-19 19:53:18 +00:00
abspos . x + = pos . x ; abspos . y + = pos . y ; abspos . z + = pos . z ;
father = [ father owner ] ;
r_mat = [ father rotationMatrix ] ;
}
glPopMatrix ( ) ; // one down
glPushMatrix ( ) ;
// position and orientation is absolute
glTranslated ( abspos . x , abspos . y , abspos . z ) ;
glMultMatrixf ( rotMatrix ) ;
[ self drawEntity : immediate : translucent ] ;
// NSLog ( @ "drawn active entity : %@" , basefile ) ;
}
}
- ( void ) initialiseTextures
{
// roll out each face and tetxure in turn
//
int fi , ti ;
//
for ( fi = 0 ; fi < n_faces ; fi + + )
{
// texture
if ( ( faces [ fi ] . texName = = 0 ) && ( faces [ fi ] . textureFile ) )
{
// load texture into Universe texturestore
2005-05-06 20:13:49 +00:00
// NSLog ( @ "Off to load %@" , faces [ fi ] . textureFile ) ;
2005-04-19 19:53:18 +00:00
if ( universe )
{
faces [ fi ] . texName = [ [ universe textureStore ] getTextureNameFor : faces [ fi ] . textureFile ] ;
}
}
}
for ( ti = 1 ; ti <= n_textures ; ti + + )
{
if ( ! texture_name [ ti ] )
{
texture_name [ ti ] = [ [ universe textureStore ] getTextureNameFor : texture_file [ ti ] ] ;
// NSLog ( @ "DEBUG (initialiseTextures) Processed textureFile : %@ to texName : %d" , entityData [ ti ] . textureFile , entityData [ ti ] . texName ) ;
}
}
}
- ( void ) regenerateDisplayList
{
glDeleteLists ( displayListName , 1 ) ;
displayListName = 0 ;
}
- ( void ) generateDisplayList
{
displayListName = glGenLists ( 1 ) ;
if ( displayListName ! = 0 )
{
glNewList ( displayListName , GL_COMPILE ) ;
2005-05-06 20:13:49 +00:00
[ self drawEntity : YES : NO ] ; // immediate YES translucent NO
2005-04-19 19:53:18 +00:00
glEndList ( ) ;
2005-05-21 08:15:49 +00:00
//
checkGLErrors ( [ NSString stringWithFormat : @ "Entity after generateDisplayList for %@" , self ] ) ;
//
2005-04-19 19:53:18 +00:00
}
}
- ( void ) update : ( double ) delta_t
{
Entity * player = [ universe entityZero ] ;
if ( player )
{
2005-05-06 20:13:49 +00:00
Vector p0 = player -> position ;
2005-04-19 19:53:18 +00:00
relative_position = make_vector ( position . x - p0 . x , position . y - p0 . y , position . z - p0 . z ) ;
zero_distance = magnitude2 ( relative_position ) ;
}
else
zero_distance = -1 ;
2005-05-23 13:23:51 +00:00
has_moved = ( ( position . x ! = last_position . x ) || ( position . y ! = last_position . y ) || ( position . z ! = last_position . z ) ) ;
last_position = position ;
has_rotated = ( ( q_rotation . w ! = last_q _rotation . w ) || ( q_rotation . x ! = last_q _rotation . x ) || ( q_rotation . y ! = last_q _rotation . y ) || ( q_rotation . z ! = last_q _rotation . z ) ) ;
last_q _rotation = q_rotation ;
2005-04-19 19:53:18 +00:00
}
- ( void ) saveToLastFrame
{
double t_now = [ universe getTime ] ;
if ( t_now >= track_time + 0.1 ) // update every 1 / 10 of a second
{
// save previous data
track_time = t_now ;
track [ track_index ] . position = position ;
track [ track_index ] . q_rotation = q_rotation ;
track [ track_index ] . timeframe = track_time ;
track_index = ( track_index + 1 ) & 0 xff ;
2005-05-06 20:13:49 +00:00
// if ( isPlayer )
2005-04-19 19:53:18 +00:00
// NSLog ( @ "Saving frame %d %.2f" , track_index , track_time ) ;
}
}
- ( BOOL ) resetToTime : ( double ) t_frame // timeframe is relative to now ie . -0.5 = half a second ago .
{
if ( t_frame >= 0 )
return NO ;
Frame selectedFrame = [ self frameAtTime : t_frame ] ;
[ self setPosition : selectedFrame . position ] ;
[ self setQRotation : selectedFrame . q_rotation ] ;
return YES ;
}
- ( Frame ) frameAtTime : ( double ) t_frame // t_frame is relative to now ie . -0.5 = half a second ago .
{
Frame result ;
result . position = position ;
result . q_rotation = q_rotation ;
result . timeframe = [ universe getTime ] ;
//
if ( t_frame >= 0.0 )
return result ;
//
double moment_in _time = [ universe getTime ] + t_frame ;
if ( moment_in _time >= track_time ) // between the last saved frame and now
{
int t1 = ( track_index - 1 ) & 0 xff ; // last saved moment
double period = result . timeframe - track_time ;
double f0 = ( result . timeframe - moment_in _time ) / period ;
double f1 = 1 - f0 ;
Vector posn ;
posn . x = f0 * result . position . x + f1 * track [ t1 ] . position . x ;
posn . y = f0 * result . position . y + f1 * track [ t1 ] . position . y ;
posn . z = f0 * result . position . z + f1 * track [ t1 ] . position . z ;
Quaternion qrot ;
qrot . w = f0 * result . q_rotation . w + f1 * track [ t1 ] . q_rotation . w ;
qrot . x = f0 * result . q_rotation . x + f1 * track [ t1 ] . q_rotation . x ;
qrot . y = f0 * result . q_rotation . y + f1 * track [ t1 ] . q_rotation . y ;
qrot . z = f0 * result . q_rotation . z + f1 * track [ t1 ] . q_rotation . z ;
result . position = posn ;
result . q_rotation = qrot ;
result . timeframe = moment_in _time ;
return result ;
}
//
if ( moment_in _time < track [ track_index ] . timeframe ) // more than 256 frames back
{
return track [ track_index ] ;
}
//
int t1 = ( track_index - 1 ) & 0 xff ;
while ( moment_in _time < track [ t1 ] . timeframe )
t1 = ( t1 - 1 ) & 0 xff ;
int t0 = ( t1 + 1 ) & 0 xff ;
// interpolate between t0 and t1
double period = track [ 0 ] . timeframe - track [ 1 ] . timeframe ;
double f0 = ( track [ t0 ] . timeframe - moment_in _time ) / period ;
double f1 = 1 - f0 ;
Vector posn ;
posn . x = f0 * track [ t0 ] . position . x + f1 * track [ t1 ] . position . x ;
posn . y = f0 * track [ t0 ] . position . y + f1 * track [ t1 ] . position . y ;
posn . z = f0 * track [ t0 ] . position . z + f1 * track [ t1 ] . position . z ;
Quaternion qrot ;
qrot . w = f0 * track [ t0 ] . q_rotation . w + f1 * track [ t1 ] . q_rotation . w ;
qrot . x = f0 * track [ t0 ] . q_rotation . x + f1 * track [ t1 ] . q_rotation . x ;
qrot . y = f0 * track [ t0 ] . q_rotation . y + f1 * track [ t1 ] . q_rotation . y ;
qrot . z = f0 * track [ t0 ] . q_rotation . z + f1 * track [ t1 ] . q_rotation . z ;
result . position = posn ;
result . q_rotation = qrot ;
result . timeframe = moment_in _time ;
return result ;
}
- ( void ) loadData : ( NSString * ) filename
{
NSScanner * scanner ;
NSString * data = nil ;
NSMutableArray * lines ;
BOOL failFlag = NO ;
NSString * failString = @ "***** " ;
int i , j ;
BOOL using_preloaded = NO ;
if ( data_store _universe )
{
if ( [ [ data_store _universe preloadedDataFiles ] objectForKey : filename ] )
{
// NSLog ( @ "Reusing data for %@ from [data_store_universe preloadedDataFiles]" , filename ) ;
data = ( NSString * ) [ [ data_store _universe preloadedDataFiles ] objectForKey : filename ] ;
using_preloaded = YES ;
}
else
{
data = [ ResourceManager stringFromFilesNamed : filename inFolder : @ "Models" ] ;
if ( data ! = nil )
[ [ data_store _universe preloadedDataFiles ] setObject : data forKey : filename ] ;
}
}
// failsafe in case the stored data fails
if ( data = = nil )
{
data = [ ResourceManager stringFromFilesNamed : filename inFolder : @ "Models" ] ;
using_preloaded = NO ;
}
// strip out comments and commas between values
//
lines = [ NSMutableArray arrayWithArray : [ data componentsSeparatedByString : @ "\n" ] ] ;
for ( i = 0 ; i < [ lines count ] ; i + + )
{
NSString * line = [ lines objectAtIndex : i ] ;
NSArray * parts ;
//
// comments
//
parts = [ line componentsSeparatedByString : @ "#" ] ;
line = [ parts objectAtIndex : 0 ] ;
parts = [ line componentsSeparatedByString : @ "//" ] ;
line = [ parts objectAtIndex : 0 ] ;
//
// commas
//
line = [ [ line componentsSeparatedByString : @ "," ] componentsJoinedByString : @ " " ] ;
//
[ lines replaceObjectAtIndex : i withObject : line ] ;
}
data = [ lines componentsJoinedByString : @ "\n" ] ;
// NSLog ( @ "More data:\n%@" , data ) ;
scanner = [ NSScanner scannerWithString : data ] ;
// get number of vertices
//
[ scanner setScanLocation : 0 ] ; // reset
// [ scanner scanCharactersFromSet : [ NSCharacterSet whitespaceAndNewlineCharacterSet ] intoString : nil ] ;
2005-04-30 23:25:21 +00:00
if ( [ scanner scanString : @ "NVERTS" intoString : ( NSString * * ) nil ] )
2005-04-19 19:53:18 +00:00
{
int n_v ;
if ( [ scanner scanInt : & n_v ] )
n_vertices = n_v ;
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to read value of NVERTS\n" , failString ] ;
}
}
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to read NVERTS\n" , failString ] ;
}
// get number of faces
//
// [ scanner setScanLocation : 0 ] ; // reset
2005-04-30 23:25:21 +00:00
if ( [ scanner scanString : @ "NFACES" intoString : ( NSString * * ) nil ] )
2005-04-19 19:53:18 +00:00
{
int n_f ;
if ( [ scanner scanInt : & n_f ] )
n_faces = n_f ;
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to read value of NFACES\n" , failString ] ;
}
}
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to read NFACES\n" , failString ] ;
}
// get vertex data
//
// [ scanner setScanLocation : 0 ] ; // reset
2005-04-30 23:25:21 +00:00
if ( [ scanner scanString : @ "VERTEX" intoString : ( NSString * * ) nil ] )
2005-04-19 19:53:18 +00:00
{
for ( j = 0 ; j < n_vertices ; j + + )
{
float x , y , z ;
if ( ! failFlag )
{
if ( ! [ scanner scanFloat : & x ] )
failFlag = YES ;
if ( ! [ scanner scanFloat : & y ] )
failFlag = YES ;
if ( ! [ scanner scanFloat : & z ] )
failFlag = YES ;
if ( ! failFlag )
{
vertices [ j ] . x = x ; vertices [ j ] . y = y ; vertices [ j ] . z = z ;
}
else
{
failString = [ NSString stringWithFormat : @ "%@Failed to read a value for vertex[%d] in VERTEX\n" , failString , j ] ;
}
}
}
}
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to find VERTEX data\n" , failString ] ;
}
// get face data
//
2005-04-30 23:25:21 +00:00
if ( [ scanner scanString : @ "FACES" intoString : ( NSString * * ) nil ] )
2005-04-19 19:53:18 +00:00
{
for ( j = 0 ; j < n_faces ; j + + )
{
int r , g , b ;
float nx , ny , nz ;
int n_v ;
if ( ! failFlag )
{
// colors
//
if ( ! [ scanner scanInt : & r ] )
failFlag = YES ;
if ( ! [ scanner scanInt : & g ] )
failFlag = YES ;
if ( ! [ scanner scanInt : & b ] )
failFlag = YES ;
if ( ! failFlag )
{
faces [ j ] . red = r / 255.0 ; faces [ j ] . green = g / 255.0 ; faces [ j ] . blue = b / 255.0 ;
}
else
{
failString = [ NSString stringWithFormat : @ "%@Failed to read a color for face[%d] in FACES\n" , failString , j ] ;
}
// normal
//
if ( ! [ scanner scanFloat : & nx ] )
failFlag = YES ;
if ( ! [ scanner scanFloat : & ny ] )
failFlag = YES ;
if ( ! [ scanner scanFloat : & nz ] )
failFlag = YES ;
if ( ! failFlag )
{
faces [ j ] . normal . x = nx ; faces [ j ] . normal . y = ny ; faces [ j ] . normal . z = nz ;
}
else
{
failString = [ NSString stringWithFormat : @ "%@Failed to read a normal for face[%d] in FACES\n" , failString , j ] ;
}
// vertices
//
if ( [ scanner scanInt : & n_v ] )
{
faces [ j ] . n_verts = n_v ;
}
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to read number of vertices for face[%d] in FACES\n" , failString , j ] ;
}
//
if ( ! failFlag )
{
int vi ;
for ( i = 0 ; i < n_v ; i + + )
{
if ( [ scanner scanInt : & vi ] )
{
faces [ j ] . vertex [ i ] = vi ;
}
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to read vertex[%d] for face[%d] in FACES\n" , failString , i , j ] ;
}
}
}
}
}
}
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to find FACES data\n" , failString ] ;
}
NSMutableDictionary * facesForTexture = [ NSMutableDictionary dictionaryWithCapacity : MAX_TEXTURES _PER _ENTITY ] ;
// get textures data
//
2005-04-30 23:25:21 +00:00
if ( [ scanner scanString : @ "TEXTURES" intoString : ( NSString * * ) nil ] )
2005-04-19 19:53:18 +00:00
{
for ( j = 0 ; j < n_faces ; j + + )
{
NSString * texfile ;
float max_x , max_y ;
float s , t ;
if ( ! failFlag )
{
// texfile
//
2005-04-30 23:25:21 +00:00
[ scanner scanCharactersFromSet : [ NSCharacterSet whitespaceAndNewlineCharacterSet ] intoString : ( NSString * * ) nil ] ;
2005-04-19 19:53:18 +00:00
if ( ! [ scanner scanUpToCharactersFromSet : [ NSCharacterSet whitespaceCharacterSet ] intoString : & texfile ] )
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to read texture filename for face[%d] in TEXTURES\n" , failString , j ] ;
}
else
{
faces [ j ] . textureFile = [ texfile retain ] ;
// create / extend a list of faces for this texture
NSMutableArray * facesForThisTexture ;
if ( [ facesForTexture objectForKey : texfile ] )
facesForThisTexture = ( NSMutableArray * ) [ facesForTexture objectForKey : texfile ] ;
else
facesForThisTexture = [ NSMutableArray arrayWithCapacity : 32 ] ;
[ facesForThisTexture addObject : [ NSNumber numberWithInt : j ] ] ;
[ facesForTexture setObject : facesForThisTexture forKey : texfile ] ;
}
faces [ j ] . texName = 0 ;
// texture size
//
if ( ! failFlag )
{
if ( ! [ scanner scanFloat : & max_x ] )
failFlag = YES ;
if ( ! [ scanner scanFloat : & max_y ] )
failFlag = YES ;
if ( failFlag )
failString = [ NSString stringWithFormat : @ "%@Failed to read texture size for max_x and max_y in face[%d] in TEXTURES\n" , failString , j ] ;
}
// vertices
//
if ( ! failFlag )
{
for ( i = 0 ; i < faces [ j ] . n_verts ; i + + )
{
if ( ! [ scanner scanFloat : & s ] )
failFlag = YES ;
if ( ! [ scanner scanFloat : & t ] )
failFlag = YES ;
if ( ! failFlag )
{
faces [ j ] . s [ i ] = s / max_x ; faces [ j ] . t [ i ] = t / max_y ;
// NSLog ( @ " st %f %f" , faces [ j ] . s [ i ] , faces [ j ] . t [ i ] ) ;
}
else
failString = [ NSString stringWithFormat : @ "%@Failed to read s t coordinates for vertex[%d] in face[%d] in TEXTURES\n" , failString , i , j ] ;
}
}
}
}
}
else
{
failFlag = YES ;
failString = [ NSString stringWithFormat : @ "%@Failed to find TEXTURES data\n" , failString ] ;
}
// NSLog ( @ "Loading data for %@: facesForTexture:\n%@" , filename , [ facesForTexture description ] ) ;
// check normals before creating new textures
//
[ self checkNormalsAndAdjustWinding ] ;
if ( ( failFlag ) && ( [ failString rangeOfString : @ "TEXTURES" ] . location ! = NSNotFound ) )
{
// NSLog ( @ "Off to make new textures!" ) ;
[ self fakeTexturesWithImageFile : @ "metal.png" andMaxSize : NSMakeSize ( 256.0 , 256.0 ) ] ;
// dump out data for ships with faked textures
2005-05-06 20:13:49 +00:00
// if ( isShip )
2005-04-19 19:53:18 +00:00
// // NSLog ( @ "Faked Texture coordinates for this model :\n\n%@\n\n" , [ self toString ] ) ;
}
if ( failFlag )
NSLog ( [ NSString stringWithFormat : @ "%@ ..... from %@ %@" , failString , filename , ( using_preloaded ) ? @ "(from preloaded data)" : @ "(from file)" ] ) ;
// set the collision radius
//
collision_radius = [ self findCollisionRadius ] ;
2005-05-21 08:15:49 +00:00
// check for smooth chading and recalculate normals
//
if ( is_smooth _shaded )
[ self calculateVertexNormals ] ;
//
// set up vertex arrays for drawing
2005-04-19 19:53:18 +00:00
//
[ self setUpVertexArrays ] ;
//
//
usingVAR = [ self OGL_InitVAR ] ;
//
if ( usingVAR )
{
[ self OGL_AssignVARMemory : sizeof ( EntityData ) : ( void * ) & entityData : 0 ] ;
}
//
}
- ( void ) checkNormalsAndAdjustWinding
{
Vector calculatedNormal ;
int i , j ;
for ( i = 0 ; i < n_faces ; i + + )
{
Vector v0 , v1 , v2 , norm ;
v0 = vertices [ faces [ i ] . vertex [ 0 ] ] ;
v1 = vertices [ faces [ i ] . vertex [ 1 ] ] ;
v2 = vertices [ faces [ i ] . vertex [ 2 ] ] ;
norm = faces [ i ] . normal ;
calculatedNormal = normal_to _surface ( v2 , v1 , v0 ) ;
if ( ( norm . x = = 0.0 ) && ( norm . y = = 0.0 ) && ( norm . z = = 0.0 ) )
{
// NSLog ( @ "Using calculated normal for face %d" , i ) ;
faces [ i ] . normal = normal_to _surface ( v0 , v1 , v2 ) ;
norm = normal_to _surface ( v0 , v1 , v2 ) ;
}
if ( ( norm . x * calculatedNormal . x < 0 ) || ( norm . y * calculatedNormal . y < 0 ) || ( norm . z * calculatedNormal . z < 0 ) )
{
// normal lies in the WRONG direction !
// reverse the winding
int v [ faces [ i ] . n_verts ] ;
GLfloat s [ faces [ i ] . n_verts ] ;
GLfloat t [ faces [ i ] . n_verts ] ;
//
// NSLog ( @ "Normal pointing the wrong way for winding on face %d" , i ) ;
//
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
v [ j ] = faces [ i ] . vertex [ faces [ i ] . n_verts - 1 - j ] ;
s [ j ] = faces [ i ] . s [ faces [ i ] . n_verts - 1 - j ] ;
t [ j ] = faces [ i ] . t [ faces [ i ] . n_verts - 1 - j ] ;
}
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
faces [ i ] . vertex [ j ] = v [ j ] ;
faces [ i ] . s [ j ] = s [ j ] ;
faces [ i ] . t [ j ] = t [ j ] ;
}
}
}
}
- ( void ) calculateVertexNormals
{
2005-05-21 08:15:49 +00:00
// int i , j ;
// for ( i = 0 ; i < n_vertices ; i + + )
// {
// int shared_faces = 0 ;
// Vector normal_sum ;
// normal_sum . x = 0.0 ; normal_sum . y = 0.0 ; normal_sum . z = 0.0 ;
// for ( j = 0 ; j < n_faces ; j + + )
// {
// BOOL is_shared = ( ( faces [ j ] . vertex [ 0 ] = = i ) || ( faces [ j ] . vertex [ 1 ] = = i ) || ( faces [ j ] . vertex [ 2 ] = = i ) ) ;
// if ( is_shared )
// {
// normal_sum . x + = faces [ j ] . normal . x ; normal_sum . y + = faces [ j ] . normal . y ; normal_sum . z + = faces [ j ] . normal . z ;
// shared_faces + + ;
// }
// }
// normal_sum = unit_vector ( & normal_sum ) ;
// vertex_normal [ i ] = normal_sum ;
// }
int i , j ;
float triangle_area [ n_faces ] ;
for ( i = 0 ; i < n_faces ; i + + )
{
// calculate areas using Herons formula
// in the form Area = sqrt ( 2 * ( a2 * b2 + b2 * c2 + c2 * a2 ) - ( a4 + b4 + c4 ) ) / 4
float a2 = distance2 ( vertices [ faces [ i ] . vertex [ 0 ] ] , vertices [ faces [ i ] . vertex [ 1 ] ] ) ;
float b2 = distance2 ( vertices [ faces [ i ] . vertex [ 1 ] ] , vertices [ faces [ i ] . vertex [ 2 ] ] ) ;
float c2 = distance2 ( vertices [ faces [ i ] . vertex [ 2 ] ] , vertices [ faces [ i ] . vertex [ 0 ] ] ) ;
triangle_area [ i ] = sqrt ( 2.0 * ( a2 * b2 + b2 * c2 + c2 * a2 ) - 0.25 * ( a2 * a2 + b2 * b2 + c2 * c2 ) ) ;
}
2005-04-19 19:53:18 +00:00
for ( i = 0 ; i < n_vertices ; i + + )
{
Vector normal_sum ;
normal_sum . x = 0.0 ; normal_sum . y = 0.0 ; normal_sum . z = 0.0 ;
for ( j = 0 ; j < n_faces ; j + + )
{
2005-05-21 08:15:49 +00:00
BOOL is_shared = ( ( faces [ j ] . vertex [ 0 ] = = i ) || ( faces [ j ] . vertex [ 1 ] = = i ) || ( faces [ j ] . vertex [ 2 ] = = i ) ) ;
2005-04-19 19:53:18 +00:00
if ( is_shared )
{
2005-05-21 08:15:49 +00:00
float t = triangle_area [ j ] ; // weight sum by area
normal_sum . x + = t * faces [ j ] . normal . x ; normal_sum . y + = t * faces [ j ] . normal . y ; normal_sum . z + = t * faces [ j ] . normal . z ;
2005-04-19 19:53:18 +00:00
}
}
normal_sum = unit_vector ( & normal_sum ) ;
2005-05-21 08:15:49 +00:00
vertex_normal [ i ] = normal_sum ;
2005-04-19 19:53:18 +00:00
}
}
- ( void ) setUpVertexArrays
{
NSMutableDictionary * texturesProcessed = [ NSMutableDictionary dictionaryWithCapacity : MAX_TEXTURES _PER _ENTITY ] ;
int face , fi , vi , texi ;
2005-05-21 08:15:49 +00:00
// base model , flat or smooth shaded , all triangles
2005-04-19 19:53:18 +00:00
int tri_index = 0 ;
2005-05-21 08:15:49 +00:00
int uv_index = 0 ;
2005-04-19 19:53:18 +00:00
int vertex_index = 0 ;
2005-05-21 08:15:49 +00:00
// int normal_index = 0 ;
2005-04-19 19:53:18 +00:00
entityData . textureFile = nil ;
entityData . texName = 0 ;
texi = 1 ; // index of first texture
for ( face = 0 ; face < n_faces ; face + + )
{
NSString * tex_string = faces [ face ] . textureFile ;
if ( ! [ texturesProcessed objectForKey : tex_string ] )
{
// do this texture
triangle_range [ texi ] . location = tri_index ;
texture_file [ texi ] = tex_string ;
texture_name [ texi ] = faces [ face ] . texName ;
for ( fi = 0 ; fi < n_faces ; fi + + )
{
Vector normal ;
int v ;
if ( ! is_smooth _shaded )
normal = faces [ fi ] . normal ;
if ( [ faces [ fi ] . textureFile isEqual : tex_string ] )
{
for ( vi = 0 ; vi < 3 ; vi + + )
{
v = faces [ fi ] . vertex [ vi ] ;
if ( is_smooth _shaded )
normal = vertex_normal [ v ] ;
entityData . index_array [ tri_index + + ] = vertex_index ;
2005-05-21 08:15:49 +00:00
entityData . normal_array [ vertex_index ] = normal ;
2005-04-19 19:53:18 +00:00
entityData . vertex_array [ vertex_index + + ] = vertices [ v ] ;
entityData . texture_uv _array [ uv_index + + ] = faces [ fi ] . s [ vi ] ;
entityData . texture_uv _array [ uv_index + + ] = faces [ fi ] . t [ vi ] ;
}
}
}
triangle_range [ texi ] . length = tri_index - triangle_range [ texi ] . location ;
// NSLog ( @ "DEBUG processing %@ texture %@ texName %d triangles %d to %d" ,
// basefile , texture_file [ texi ] , texture_name [ texi ] , triangle_range [ texi ] . location , triangle_range [ texi ] . location + triangle_range [ texi ] . length ) ;
// finally . . .
[ texturesProcessed setObject : tex_string forKey : tex_string ] ; // note this texture done
texi + + ;
}
}
entityData . n_triangles = tri_index ; // total number of triangle vertices
triangle_range [ 0 ] = NSMakeRange ( 0 , tri_index ) ;
n_textures = texi - 1 ;
}
- ( double ) findCollisionRadius
{
int i ;
double d_squared , result , length_longest _axis , length_shortest _axis ;
result = 0.0 ;
bounding_box _reset ( & boundingBox ) ;
for ( i = 0 ; i < n_vertices ; i + + )
{
d_squared = vertices [ i ] . x * vertices [ i ] . x + vertices [ i ] . y * vertices [ i ] . y + vertices [ i ] . z * vertices [ i ] . z ;
if ( d_squared > result )
result = d_squared ;
bounding_box _add _vector ( & boundingBox , vertices [ i ] ) ;
}
length_longest _axis = boundingBox . max_x - boundingBox . min_x ;
if ( boundingBox . max_y - boundingBox . min_y > length_longest _axis )
length_longest _axis = boundingBox . max_y - boundingBox . min_y ;
if ( boundingBox . max_z - boundingBox . min_z > length_longest _axis )
length_longest _axis = boundingBox . max_z - boundingBox . min_z ;
length_shortest _axis = boundingBox . max_x - boundingBox . min_x ;
if ( boundingBox . max_y - boundingBox . min_y < length_shortest _axis )
length_shortest _axis = boundingBox . max_y - boundingBox . min_y ;
if ( boundingBox . max_z - boundingBox . min_z < length_shortest _axis )
length_shortest _axis = boundingBox . max_z - boundingBox . min_z ;
d_squared = ( length_longest _axis + length_shortest _axis ) * ( length_longest _axis + length_shortest _axis ) * 0.25 ; // square of average length
no_draw _distance = d_squared * NO_DRAW _DISTANCE _FACTOR * NO_DRAW _DISTANCE _FACTOR ; // no longer based on the collision radius
mass = ( boundingBox . max_x - boundingBox . min_x ) * ( boundingBox . max_y - boundingBox . min_y ) * ( boundingBox . max_z - boundingBox . min_z ) ;
// NSLog ( @ "%@ has mass %.3f" , basefile , mass ) ;
return sqrt ( result ) ;
}
- ( BoundingBox ) findBoundingBoxRelativeTo : ( Entity * ) other InVectors : ( Vector ) _i : ( Vector ) _j : ( Vector ) _k
{
Vector pv , rv ;
Vector rpos = position ;
2005-05-06 20:13:49 +00:00
Vector opv = ( other ) ? other -> position : rpos ;
2005-04-19 19:53:18 +00:00
rpos . x - = opv . x ; rpos . y - = opv . y ; rpos . z - = opv . z ;
rv . x = dot_product ( _i , rpos ) ;
rv . y = dot_product ( _j , rpos ) ;
rv . z = dot_product ( _k , rpos ) ;
BoundingBox result ;
bounding_box _reset _to _vector ( & result , rv ) ;
int i ;
for ( i = 0 ; i < n_vertices ; i + + )
{
pv . x = rpos . x + vertices [ i ] . x ;
pv . y = rpos . y + vertices [ i ] . y ;
pv . z = rpos . z + vertices [ i ] . z ;
rv . x = dot_product ( _i , pv ) ;
rv . y = dot_product ( _j , pv ) ;
rv . z = dot_product ( _k , pv ) ;
bounding_box _add _vector ( & result , rv ) ;
}
return result ;
}
- ( BoundingBox ) findBoundingBoxRelativeToPosition : ( Vector ) opv InVectors : ( Vector ) _i : ( Vector ) _j : ( Vector ) _k
{
Vector pv , rv ;
Vector rpos = position ;
rpos . x - = opv . x ; rpos . y - = opv . y ; rpos . z - = opv . z ;
rv . x = dot_product ( _i , rpos ) ;
rv . y = dot_product ( _j , rpos ) ;
rv . z = dot_product ( _k , rpos ) ;
BoundingBox result ;
bounding_box _reset _to _vector ( & result , rv ) ;
int i ;
for ( i = 0 ; i < n_vertices ; i + + )
{
pv . x = rpos . x + vertices [ i ] . x ;
pv . y = rpos . y + vertices [ i ] . y ;
pv . z = rpos . z + vertices [ i ] . z ;
rv . x = dot_product ( _i , pv ) ;
rv . y = dot_product ( _j , pv ) ;
rv . z = dot_product ( _k , pv ) ;
bounding_box _add _vector ( & result , rv ) ;
}
return result ;
}
- ( BOOL ) checkCloseCollisionWith : ( Entity * ) other
{
return YES ;
}
- ( void ) takeEnergyDamage : ( double ) amount from : ( Entity * ) ent becauseOf : ( Entity * ) other
{
}
- ( NSString * ) toString
{
// produce a file from the original data
int i , j , r , g , b ;
NSString * result ;
NSString * boilerplate = @ "# This is a file adapted from the model files for Java Elite\n# which in turn are based on the data released by Ian Bell\n# in the file b7051600.zip at\n# http://www.users.waitrose.com/~elitearc2/elite/archive/b7051600.zip\n#" ;
result = [ NSString stringWithFormat : @ "%@\n# %@\n#\n\nNVERTS %d\nNFACES %d\n\nVERTEX\n" , boilerplate , basefile , n_vertices , n_faces ] ;
for ( i = 0 ; i < n_vertices ; i + + )
{
result = [ NSString stringWithFormat : @ "%@%f,\t%f,\t%f\n" , result , vertices [ i ] . x , vertices [ i ] . y , vertices [ i ] . z ] ;
if ( ( i % 5 ) = = 4 )
result = [ NSString stringWithFormat : @ "%@\n" , result ] ;
}
result = [ NSString stringWithFormat : @ "%@\nFACES\n" , result ] ;
//
// NSLog ( result ) ;
//
for ( j = 0 ; j < n_faces ; j + + )
{
r = ( int ) ( faces [ j ] . red * 255.0 ) ; g = ( int ) ( faces [ j ] . green * 255.0 ) ; b = ( int ) ( faces [ j ] . blue * 255.0 ) ;
result = [ NSString stringWithFormat : @ "%@%d, %d, %d,\t" , result , r , g , b ] ;
result = [ NSString stringWithFormat : @ "%@%f, %f, %f,\t" , result , faces [ j ] . normal . x , faces [ j ] . normal . y , faces [ j ] . normal . z ] ;
result = [ NSString stringWithFormat : @ "%@%d,\t" , result , faces [ j ] . n_verts ] ;
for ( i = 0 ; i < faces [ j ] . n_verts ; i + + )
{
result = [ NSString stringWithFormat : @ "%@%d " , result , faces [ j ] . vertex [ i ] ] ;
}
result = [ NSString stringWithFormat : @ "%@\n" , result ] ;
}
if ( universe )
{
result = [ NSString stringWithFormat : @ "%@\nTEXTURES\n" , result ] ;
for ( j = 0 ; j < n_faces ; j + + )
{
NSSize texSize = [ [ universe textureStore ] getSizeOfTexture : faces [ j ] . textureFile ] ;
result = [ NSString stringWithFormat : @ "%@%@\t%d %d" , result , faces [ j ] . textureFile , ( int ) texSize . width , ( int ) texSize . height ] ;
for ( i = 0 ; i < faces [ j ] . n_verts ; i + + )
{
int s = ( int ) ( faces [ j ] . s [ i ] * texSize . width ) ;
int t = ( int ) ( faces [ j ] . t [ i ] * texSize . height ) ;
result = [ NSString stringWithFormat : @ "%@\t%d %d" , result , s , t ] ;
}
result = [ NSString stringWithFormat : @ "%@\n" , result ] ;
}
}
result = [ NSString stringWithFormat : @ "%@\nEND\n" , result ] ;
return result ;
}
- ( void ) fakeTexturesWithImageFile : ( NSString * ) textureFile andMaxSize : ( NSSize ) maxSize
{
int i , j , k ;
Vector vec ;
int nf = 0 ;
int fi [ MAX_FACES _PER _ENTITY ] ;
float max_s , min_s , max_t , min_t , st_width , st_height ;
float tolerance ;
Face fa [ MAX_FACES _PER _ENTITY ] ;
int faces_to _match ;
BOOL face_matched [ MAX_FACES _PER _ENTITY ] ;
tolerance = 1.00 ;
faces_to _match = n_faces ;
for ( i = 0 ; i < n_faces ; i + + )
{
face_matched [ i ] = NO ;
}
while ( faces_to _match > 0 )
{
tolerance - = 0.05 ;
// Top ( + y ) first
vec . x = 0.0 ; vec . y = 1.0 ; vec . z = 0.0 ;
// build list of faces that face in that direction . . .
nf = 0 ;
max_s = -999999.0 ; min_s = 999999.0 ;
max_t = -999999.0 ; min_t = 999999.0 ;
for ( i = 0 ; i < n_faces ; i + + )
{
float s , t ;
float g = dot_product ( vec , faces [ i ] . normal ) * sqrt ( 2.0 ) ;
if ( ( g >= tolerance ) && ( ! face_matched [ i ] ) )
{
fi [ nf + + ] = i ;
face_matched [ i ] = YES ;
faces_to _match - - ;
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
s = vertices [ faces [ i ] . vertex [ j ] ] . x ;
t = vertices [ faces [ i ] . vertex [ j ] ] . z ;
max_s = ( max_s > s ) ? max_s : s ; min_s = ( min_s < s ) ? min_s : s ;
max_t = ( max_t > t ) ? max_t : t ; min_t = ( min_t < t ) ? min_t : t ;
}
}
}
//
st_width = max_s - min_s ;
st_height = max_t - min_t ;
//
// NSLog ( @ "TOP st_width %f st_height %f maxSize.height %f maxSize.width %f" , st_width , st_height , maxSize . width , maxSize . height ) ;
//
for ( j = 0 ; j < nf ; j + + )
{
i = fi [ j ] ;
// fa [ i ] = faces [ i ] ;
fa [ i ] . textureFile = [ NSString stringWithFormat : @ "top_%@" , textureFile ] ;
for ( k = 0 ; k < faces [ i ] . n_verts ; k + + )
{
float s , t ;
s = vertices [ faces [ i ] . vertex [ k ] ] . x ;
t = vertices [ faces [ i ] . vertex [ k ] ] . z ;
fa [ i ] . s [ k ] = ( s - min_s ) * maxSize . width / st_width ;
fa [ i ] . t [ k ] = ( t - min_t ) * maxSize . height / st_height ;
//
// TESTING
//
fa [ i ] . t [ k ] = maxSize . height - fa [ i ] . t [ k ] ; // REVERSE t locations
//
// NSLog ( @ "%f, %f" , fa [ i ] . s [ k ] , fa [ i ] . t [ k ] ) ;
//
}
}
// Bottom ( - y )
vec . x = 0.0 ; vec . y = -1.0 ; vec . z = 0.0 ;
// build list of faces that face in that direction . . .
nf = 0 ;
max_s = -999999.0 ; min_s = 999999.0 ;
max_t = -999999.0 ; min_t = 999999.0 ;
for ( i = 0 ; i < n_faces ; i + + )
{
float s , t ;
float g = dot_product ( vec , faces [ i ] . normal ) * sqrt ( 2.0 ) ;
if ( ( g >= tolerance ) && ( ! face_matched [ i ] ) )
{
fi [ nf + + ] = i ;
face_matched [ i ] = YES ;
faces_to _match - - ;
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
s = - vertices [ faces [ i ] . vertex [ j ] ] . x ;
t = - vertices [ faces [ i ] . vertex [ j ] ] . z ;
max_s = ( max_s > s ) ? max_s : s ; min_s = ( min_s < s ) ? min_s : s ;
max_t = ( max_t > t ) ? max_t : t ; min_t = ( min_t < t ) ? min_t : t ;
}
}
}
st_width = max_s - min_s ;
st_height = max_t - min_t ;
for ( j = 0 ; j < nf ; j + + )
{
i = fi [ j ] ;
// fa [ i ] = faces [ i ] ;
fa [ i ] . textureFile = [ NSString stringWithFormat : @ "bottom_%@" , textureFile ] ;
for ( k = 0 ; k < faces [ i ] . n_verts ; k + + )
{
float s , t ;
s = - vertices [ faces [ i ] . vertex [ k ] ] . x ;
t = - vertices [ faces [ i ] . vertex [ k ] ] . z ;
fa [ i ] . s [ k ] = ( s - min_s ) * maxSize . width / st_width ;
fa [ i ] . t [ k ] = ( t - min_t ) * maxSize . height / st_height ;
}
}
// Right ( + x )
vec . x = 1.0 ; vec . y = 0.0 ; vec . z = 0.0 ;
// build list of faces that face in that direction . . .
nf = 0 ;
max_s = -999999.0 ; min_s = 999999.0 ;
max_t = -999999.0 ; min_t = 999999.0 ;
for ( i = 0 ; i < n_faces ; i + + )
{
float s , t ;
float g = dot_product ( vec , faces [ i ] . normal ) * sqrt ( 2.0 ) ;
if ( ( g >= tolerance ) && ( ! face_matched [ i ] ) )
{
fi [ nf + + ] = i ;
face_matched [ i ] = YES ;
faces_to _match - - ;
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
s = vertices [ faces [ i ] . vertex [ j ] ] . z ;
t = vertices [ faces [ i ] . vertex [ j ] ] . y ;
max_s = ( max_s > s ) ? max_s : s ; min_s = ( min_s < s ) ? min_s : s ;
max_t = ( max_t > t ) ? max_t : t ; min_t = ( min_t < t ) ? min_t : t ;
}
}
}
st_width = max_s - min_s ;
st_height = max_t - min_t ;
for ( j = 0 ; j < nf ; j + + )
{
i = fi [ j ] ;
// fa [ i ] = faces [ i ] ;
fa [ i ] . textureFile = [ NSString stringWithFormat : @ "right_%@" , textureFile ] ;
for ( k = 0 ; k < faces [ i ] . n_verts ; k + + )
{
float s , t ;
s = vertices [ faces [ i ] . vertex [ k ] ] . z ;
t = vertices [ faces [ i ] . vertex [ k ] ] . y ;
fa [ i ] . s [ k ] = ( s - min_s ) * maxSize . width / st_width ;
fa [ i ] . t [ k ] = ( t - min_t ) * maxSize . height / st_height ;
}
}
// Left ( - x )
vec . x = -1.0 ; vec . y = 0.0 ; vec . z = 0.0 ;
// build list of faces that face in that direction . . .
nf = 0 ;
max_s = -999999.0 ; min_s = 999999.0 ;
max_t = -999999.0 ; min_t = 999999.0 ;
for ( i = 0 ; i < n_faces ; i + + )
{
float s , t ;
float g = dot_product ( vec , faces [ i ] . normal ) * sqrt ( 2.0 ) ;
if ( ( g >= tolerance ) && ( ! face_matched [ i ] ) )
{
fi [ nf + + ] = i ;
face_matched [ i ] = YES ;
faces_to _match - - ;
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
s = - vertices [ faces [ i ] . vertex [ j ] ] . z ;
t = - vertices [ faces [ i ] . vertex [ j ] ] . y ;
max_s = ( max_s > s ) ? max_s : s ; min_s = ( min_s < s ) ? min_s : s ;
max_t = ( max_t > t ) ? max_t : t ; min_t = ( min_t < t ) ? min_t : t ;
}
}
}
st_width = max_s - min_s ;
st_height = max_t - min_t ;
for ( j = 0 ; j < nf ; j + + )
{
i = fi [ j ] ;
// fa [ i ] = faces [ i ] ;
fa [ i ] . textureFile = [ NSString stringWithFormat : @ "left_%@" , textureFile ] ;
for ( k = 0 ; k < faces [ i ] . n_verts ; k + + )
{
float s , t ;
s = - vertices [ faces [ i ] . vertex [ k ] ] . z ;
t = - vertices [ faces [ i ] . vertex [ k ] ] . y ;
fa [ i ] . s [ k ] = ( s - min_s ) * maxSize . width / st_width ;
fa [ i ] . t [ k ] = ( t - min_t ) * maxSize . height / st_height ;
}
}
// Front ( + z )
vec . x = 0.0 ; vec . y = 0.0 ; vec . z = 1.0 ;
// build list of faces that face in that direction . . .
nf = 0 ;
max_s = -999999.0 ; min_s = 999999.0 ;
max_t = -999999.0 ; min_t = 999999.0 ;
for ( i = 0 ; i < n_faces ; i + + )
{
float s , t ;
float g = dot_product ( vec , faces [ i ] . normal ) * sqrt ( 2.0 ) ;
if ( ( g >= tolerance ) && ( ! face_matched [ i ] ) )
{
fi [ nf + + ] = i ;
face_matched [ i ] = YES ;
faces_to _match - - ;
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
s = vertices [ faces [ i ] . vertex [ j ] ] . x ;
t = vertices [ faces [ i ] . vertex [ j ] ] . y ;
max_s = ( max_s > s ) ? max_s : s ; min_s = ( min_s < s ) ? min_s : s ;
max_t = ( max_t > t ) ? max_t : t ; min_t = ( min_t < t ) ? min_t : t ;
}
}
}
st_width = max_s - min_s ;
st_height = max_t - min_t ;
for ( j = 0 ; j < nf ; j + + )
{
i = fi [ j ] ;
// fa [ i ] = faces [ i ] ;
fa [ i ] . textureFile = [ NSString stringWithFormat : @ "front_%@" , textureFile ] ;
for ( k = 0 ; k < faces [ i ] . n_verts ; k + + )
{
float s , t ;
s = vertices [ faces [ i ] . vertex [ k ] ] . x ;
t = vertices [ faces [ i ] . vertex [ k ] ] . y ;
fa [ i ] . s [ k ] = ( s - min_s ) * maxSize . width / st_width ;
fa [ i ] . t [ k ] = ( t - min_t ) * maxSize . height / st_height ;
}
}
// Back ( - z )
vec . x = 0.0 ; vec . y = 0.0 ; vec . z = -1.0 ;
// build list of faces that face in that direction . . .
nf = 0 ;
max_s = -999999.0 ; min_s = 999999.0 ;
max_t = -999999.0 ; min_t = 999999.0 ;
for ( i = 0 ; i < n_faces ; i + + )
{
float s , t ;
float g = dot_product ( vec , faces [ i ] . normal ) * sqrt ( 2.0 ) ;
if ( ( g >= tolerance ) && ( ! face_matched [ i ] ) )
{
fi [ nf + + ] = i ;
face_matched [ i ] = YES ;
faces_to _match - - ;
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
s = - vertices [ faces [ i ] . vertex [ j ] ] . x ;
t = - vertices [ faces [ i ] . vertex [ j ] ] . y ;
max_s = ( max_s > s ) ? max_s : s ; min_s = ( min_s < s ) ? min_s : s ;
max_t = ( max_t > t ) ? max_t : t ; min_t = ( min_t < t ) ? min_t : t ;
}
}
}
st_width = max_s - min_s ;
st_height = max_t - min_t ;
for ( j = 0 ; j < nf ; j + + )
{
i = fi [ j ] ;
// fa [ i ] = faces [ i ] ;
fa [ i ] . textureFile = [ NSString stringWithFormat : @ "back_%@" , textureFile ] ;
for ( k = 0 ; k < faces [ i ] . n_verts ; k + + )
{
float s , t ;
s = - vertices [ faces [ i ] . vertex [ k ] ] . x ;
t = - vertices [ faces [ i ] . vertex [ k ] ] . y ;
fa [ i ] . s [ k ] = ( s - min_s ) * maxSize . width / st_width ;
fa [ i ] . t [ k ] = ( t - min_t ) * maxSize . height / st_height ;
}
}
// NSLog ( @ "%d / %d faces matched at tolerance: %f" , n_faces - faces_to _match , n_faces , tolerance ) ;
}
for ( i = 0 ; i < n_faces ; i + + )
{
NSString * result ;
faces [ i ] . textureFile = [ fa [ i ] . textureFile retain ] ;
faces [ i ] . texName = 0 ;
for ( j = 0 ; j < faces [ i ] . n_verts ; j + + )
{
//
// NSLog ( @ "face[%d] %f, %f" , i , fa [ i ] . s [ j ] , fa [ i ] . t [ j ] ) ;
//
faces [ i ] . s [ j ] = fa [ i ] . s [ j ] / maxSize . width ;
faces [ i ] . t [ j ] = fa [ i ] . t [ j ] / maxSize . height ;
}
result = [ NSString stringWithFormat : @ "%@\t%d %d" , faces [ i ] . textureFile , ( int ) maxSize . width , ( int ) maxSize . height ] ;
// NSLog ( @ "face[%d] : %@" , i , result ) ;
}
}
// COMMON OGL STUFF
- ( BOOL ) OGL_InitVAR
{
short i ;
static char * s ;
if ( global_testForVAR )
{
global_testForVAR = NO ; // no need for further tests after this
// see if we have supported hardware
s = ( char * ) glGetString ( GL_EXTENSIONS ) ; // get extensions list
2005-04-30 23:25:21 +00:00
if ( strstr ( s , "GL_APPLE_vertex_array_range" ) = = NULL )
2005-04-19 19:53:18 +00:00
{
global_usingVAR & = NO ;
NSLog ( @ "Vertex Array Range optimisation - not supported" ) ;
return NO ;
}
else
{
NSLog ( @ "Vertex Array Range optimisation - supported" ) ;
global_usingVAR | = YES ;
}
}
if ( ! global_usingVAR )
return NO ;
# ifdef GNUSTEP
// TODO : Find out what these APPLE functions do
# else
glGenVertexArraysAPPLE ( NUM_VERTEX _ARRAY _RANGES , & gVertexArrayRangeObjects [ 0 ] ) ;
# endif
// INIT OUR DATA
//
// None of the VAR objects has been assigned to any data yet ,
// so here we just initialize our info . We ' ll assign the VAR objects
// to data later .
//
for ( i = 0 ; i < NUM_VERTEX _ARRAY _RANGES ; i + + )
{
gVertexArrayRangeData [ i ] . rangeSize = 0 ;
gVertexArrayRangeData [ i ] . dataBlockPtr = nil ;
gVertexArrayRangeData [ i ] . forceUpdate = true ;
gVertexArrayRangeData [ i ] . activated = false ;
}
return YES ;
}
- ( void ) OGL_AssignVARMemory : ( long ) size : ( void * ) data : ( Byte ) whichVAR
{
if ( whichVAR >= NUM_VERTEX _ARRAY _RANGES )
{
NSLog ( @ "VAR is out of range!" ) ;
exit ( -1 ) ;
}
gVertexArrayRangeData [ whichVAR ] . rangeSize = size ;
gVertexArrayRangeData [ whichVAR ] . dataBlockPtr = data ;
gVertexArrayRangeData [ whichVAR ] . forceUpdate = true ;
}
- ( void ) OGL_UpdateVAR
{
long size ;
Byte i ;
for ( i = 0 ; i < NUM_VERTEX _ARRAY _RANGES ; i + + )
{
// SEE IF THIS VAR IS USED
size = gVertexArrayRangeData [ i ] . rangeSize ;
if ( size = = 0 )
continue ;
// SEE IF VAR NEEDS UPDATING
if ( ! gVertexArrayRangeData [ i ] . forceUpdate )
continue ;
# ifdef GNUSTEP
// TODO : find out what non - AAPL OpenGL stuff is equivalent
# else
// BIND THIS VAR OBJECT SO WE CAN DO STUFF TO IT
2005-05-23 13:23:51 +00:00
2005-04-19 19:53:18 +00:00
glBindVertexArrayAPPLE ( gVertexArrayRangeObjects [ i ] ) ;
// SEE IF THIS IS THE FIRST TIME IN
if ( ! gVertexArrayRangeData [ i ] . activated )
{
glVertexArrayRangeAPPLE ( size , gVertexArrayRangeData [ i ] . dataBlockPtr ) ;
glVertexArrayParameteriAPPLE ( GL_VERTEX _ARRAY _STORAGE _HINT _APPLE , GL_STORAGE _SHARED _APPLE ) ;
// you MUST call this flush to get the data primed !
glFlushVertexArrayRangeAPPLE ( size , gVertexArrayRangeData [ i ] . dataBlockPtr ) ;
glEnableClientState ( GL_VERTEX _ARRAY _RANGE _APPLE ) ;
gVertexArrayRangeData [ i ] . activated = true ;
}
// ALREADY ACTIVE , SO JUST UPDATING
else
{
glFlushVertexArrayRangeAPPLE ( size , gVertexArrayRangeData [ i ] . dataBlockPtr ) ;
}
# endif
gVertexArrayRangeData [ i ] . forceUpdate = false ;
}
}
2005-05-21 08:15:49 +00:00
// log a list of current states
//
2005-06-02 13:53:02 +00:00
// we need to report on the material properties
GLfloat stored_mat _ambient [ 4 ] ;
GLfloat stored_mat _diffuse [ 4 ] ;
GLfloat stored_mat _emission [ 4 ] ;
GLfloat stored_mat _specular [ 4 ] ;
GLfloat stored_mat _shininess [ 1 ] ;
//
GLfloat stored_current _color [ 4 ] ;
//
GLint stored_gl _shade _model [ 1 ] ;
//
GLint stored_gl _texture _env _mode [ 1 ] ;
//
GLint stored_gl _cull _face _mode [ 1 ] ;
//
GLint stored_gl _front _face [ 1 ] ;
//
GLint stored_gl _blend _src [ 1 ] ;
GLint stored_gl _blend _dst [ 1 ] ;
//
GLenum stored_errCode ;
//
2005-05-21 08:15:49 +00:00
void logGLState ( )
{
// we need to report on the material properties
GLfloat mat_ambient [ 4 ] ;
GLfloat mat_diffuse [ 4 ] ;
GLfloat mat_emission [ 4 ] ;
GLfloat mat_specular [ 4 ] ;
GLfloat mat_shininess [ 1 ] ;
//
GLfloat current_color [ 4 ] ;
//
GLint gl_shade _model [ 1 ] ;
//
GLint gl_texture _env _mode [ 1 ] ;
NSString * tex_env _mode _string = nil ;
//
GLint gl_cull _face _mode [ 1 ] ;
NSString * cull_face _mode _string = nil ;
//
GLint gl_front _face [ 1 ] ;
NSString * front_face _string = nil ;
//
GLint gl_blend _src [ 1 ] ;
NSString * blend_src _string = nil ;
GLint gl_blend _dst [ 1 ] ;
NSString * blend_dst _string = nil ;
//
GLenum errCode ;
const GLubyte * errString ;
glGetMaterialfv ( GL_FRONT , GL_AMBIENT , mat_ambient ) ;
glGetMaterialfv ( GL_FRONT , GL_DIFFUSE , mat_diffuse ) ;
glGetMaterialfv ( GL_FRONT , GL_EMISSION , mat_emission ) ;
glGetMaterialfv ( GL_FRONT , GL_SPECULAR , mat_specular ) ;
glGetMaterialfv ( GL_FRONT , GL_SHININESS , mat_shininess ) ;
//
glGetFloatv ( GL_CURRENT _COLOR , current_color ) ;
//
glGetIntegerv ( GL_SHADE _MODEL , gl_shade _model ) ;
//
glGetIntegerv ( GL_BLEND _SRC , gl_blend _src ) ;
switch ( gl_blend _src [ 0 ] )
{
case GL_ZERO :
blend_src _string = @ "GL_ZERO" ;
break ;
case GL_ONE :
blend_src _string = @ "GL_ONE" ;
break ;
case GL_DST _COLOR :
blend_src _string = @ "GL_DST_COLOR" ;
break ;
case GL_SRC _COLOR :
blend_src _string = @ "GL_SRC_COLOR" ;
break ;
case GL_ONE _MINUS _DST _COLOR :
blend_src _string = @ "GL_ONE_MINUS_DST_COLOR" ;
break ;
case GL_ONE _MINUS _SRC _COLOR :
blend_src _string = @ "GL_ONE_MINUS_SRC_COLOR" ;
break ;
case GL_SRC _ALPHA :
blend_src _string = @ "GL_SRC_ALPHA" ;
break ;
case GL_DST _ALPHA :
blend_src _string = @ "GL_DST_ALPHA" ;
break ;
case GL_ONE _MINUS _SRC _ALPHA :
blend_src _string = @ "GL_ONE_MINUS_SRC_ALPHA" ;
break ;
case GL_ONE _MINUS _DST _ALPHA :
blend_src _string = @ "GL_ONE_MINUS_DST_ALPHA" ;
break ;
case GL_SRC _ALPHA _SATURATE :
blend_src _string = @ "GL_SRC_ALPHA_SATURATE" ;
break ;
default :
break ;
}
//
glGetIntegerv ( GL_BLEND _DST , gl_blend _dst ) ;
switch ( gl_blend _dst [ 0 ] )
{
case GL_ZERO :
blend_dst _string = @ "GL_ZERO" ;
break ;
case GL_ONE :
blend_dst _string = @ "GL_ONE" ;
break ;
case GL_DST _COLOR :
blend_dst _string = @ "GL_DST_COLOR" ;
break ;
case GL_SRC _COLOR :
blend_dst _string = @ "GL_SRC_COLOR" ;
break ;
case GL_ONE _MINUS _DST _COLOR :
blend_dst _string = @ "GL_ONE_MINUS_DST_COLOR" ;
break ;
case GL_ONE _MINUS _SRC _COLOR :
blend_dst _string = @ "GL_ONE_MINUS_SRC_COLOR" ;
break ;
case GL_SRC _ALPHA :
blend_dst _string = @ "GL_SRC_ALPHA" ;
break ;
case GL_DST _ALPHA :
blend_dst _string = @ "GL_DST_ALPHA" ;
break ;
case GL_ONE _MINUS _SRC _ALPHA :
blend_dst _string = @ "GL_ONE_MINUS_SRC_ALPHA" ;
break ;
case GL_ONE _MINUS _DST _ALPHA :
blend_dst _string = @ "GL_ONE_MINUS_DST_ALPHA" ;
break ;
case GL_SRC _ALPHA _SATURATE :
blend_dst _string = @ "GL_SRC_ALPHA_SATURATE" ;
break ;
default :
break ;
}
//
glGetIntegerv ( GL_CULL _FACE _MODE , gl_cull _face _mode ) ;
switch ( gl_cull _face _mode [ 0 ] )
{
case GL_BACK :
cull_face _mode _string = @ "GL_BACK" ;
break ;
case GL_FRONT :
cull_face _mode _string = @ "GL_FRONT" ;
break ;
default :
break ;
}
//
glGetIntegerv ( GL_FRONT _FACE , gl_front _face ) ;
switch ( gl_front _face [ 0 ] )
{
case GL_CCW :
front_face _string = @ "GL_CCW" ;
break ;
case GL_CW :
front_face _string = @ "GL_CW" ;
break ;
default :
break ;
}
//
glGetTexEnviv ( GL_TEXTURE _ENV , GL_TEXTURE _ENV _MODE , gl_texture _env _mode ) ;
switch ( gl_texture _env _mode [ 0 ] )
{
case GL_DECAL :
tex_env _mode _string = @ "GL_DECAL" ;
break ;
case GL_REPLACE :
tex_env _mode _string = @ "GL_REPLACE" ;
break ;
case GL_MODULATE :
tex_env _mode _string = @ "GL_MODULATE" ;
break ;
case GL_BLEND :
tex_env _mode _string = @ "GL_BLEND" ;
break ;
default :
break ;
}
//
if ( ( errCode = glGetError ( ) ) ! = GL_NO _ERROR )
{
errString = gluErrorString ( errCode ) ;
NSLog ( @ "OPENGL_DEBUG GL_ERROR (%d) %s" , errCode , errString ) ;
}
/ * - - MATERIALS - - * /
2005-06-02 13:53:02 +00:00
if ( ( stored_mat _ambient [ 0 ] ! = mat_ambient [ 0 ] ) || ( stored_mat _ambient [ 1 ] ! = mat_ambient [ 1 ] ) || ( stored_mat _ambient [ 2 ] ! = mat_ambient [ 2 ] ) || ( stored_mat _ambient [ 3 ] ! = mat_ambient [ 2 ] ) )
NSLog ( @ "OPENGL_DEBUG GL_AMBIENT ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
mat_ambient [ 0 ] , mat_ambient [ 1 ] , mat_ambient [ 2 ] , mat_ambient [ 3 ] ) ;
if ( ( stored_mat _diffuse [ 0 ] ! = mat_diffuse [ 0 ] ) || ( stored_mat _diffuse [ 1 ] ! = mat_diffuse [ 1 ] ) || ( stored_mat _diffuse [ 2 ] ! = mat_diffuse [ 2 ] ) || ( stored_mat _diffuse [ 3 ] ! = mat_diffuse [ 2 ] ) )
NSLog ( @ "OPENGL_DEBUG GL_DIFFUSE ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
mat_diffuse [ 0 ] , mat_diffuse [ 1 ] , mat_diffuse [ 2 ] , mat_diffuse [ 3 ] ) ;
if ( ( stored_mat _emission [ 0 ] ! = mat_emission [ 0 ] ) || ( stored_mat _emission [ 1 ] ! = mat_emission [ 1 ] ) || ( stored_mat _emission [ 2 ] ! = mat_emission [ 2 ] ) || ( stored_mat _emission [ 3 ] ! = mat_emission [ 2 ] ) )
NSLog ( @ "OPENGL_DEBUG GL_EMISSION ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
mat_emission [ 0 ] , mat_emission [ 1 ] , mat_emission [ 2 ] , mat_emission [ 3 ] ) ;
if ( ( stored_mat _specular [ 0 ] ! = mat_specular [ 0 ] ) || ( stored_mat _specular [ 1 ] ! = mat_specular [ 1 ] ) || ( stored_mat _specular [ 2 ] ! = mat_specular [ 2 ] ) || ( stored_mat _specular [ 3 ] ! = mat_specular [ 2 ] ) )
NSLog ( @ "OPENGL_DEBUG GL_SPECULAR ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
mat_specular [ 0 ] , mat_specular [ 1 ] , mat_specular [ 2 ] , mat_specular [ 3 ] ) ;
if ( stored_mat _shininess [ 0 ] ! = mat_shininess [ 0 ] )
NSLog ( @ "OPENGL_DEBUG GL_SHININESS ( %.2ff)" , mat_shininess [ 0 ] ) ;
stored_mat _ambient [ 0 ] = mat_ambient [ 0 ] ; stored_mat _ambient [ 1 ] = mat_ambient [ 1 ] ; stored_mat _ambient [ 2 ] = mat_ambient [ 2 ] ; stored_mat _ambient [ 3 ] = mat_ambient [ 3 ] ;
stored_mat _diffuse [ 0 ] = mat_diffuse [ 0 ] ; stored_mat _diffuse [ 1 ] = mat_diffuse [ 1 ] ; stored_mat _diffuse [ 2 ] = mat_diffuse [ 2 ] ; stored_mat _diffuse [ 3 ] = mat_diffuse [ 3 ] ;
stored_mat _emission [ 0 ] = mat_emission [ 0 ] ; stored_mat _emission [ 1 ] = mat_emission [ 1 ] ; stored_mat _emission [ 2 ] = mat_emission [ 2 ] ; stored_mat _emission [ 3 ] = mat_emission [ 3 ] ;
stored_mat _specular [ 0 ] = mat_specular [ 0 ] ; stored_mat _specular [ 1 ] = mat_specular [ 1 ] ; stored_mat _specular [ 2 ] = mat_specular [ 2 ] ; stored_mat _specular [ 3 ] = mat_specular [ 3 ] ;
stored_mat _shininess [ 0 ] = mat_shininess [ 0 ] ;
2005-05-21 08:15:49 +00:00
/ * - - MATERIALS - - * /
//
/ * - - LIGHTS - - * /
if ( glIsEnabled ( GL_LIGHTING ) )
{
NSLog ( @ "OPENGL_DEBUG GL_LIGHTING :ENABLED:" ) ;
if ( glIsEnabled ( GL_LIGHT0 ) )
NSLog ( @ "OPENGL_DEBUG GL_LIGHT0 :ENABLED:" ) ;
if ( glIsEnabled ( GL_LIGHT1 ) )
{
NSLog ( @ "OPENGL_DEBUG GL_LIGHT1 :ENABLED:" ) ;
GLfloat light_ambient [ 4 ] ;
GLfloat light_diffuse [ 4 ] ;
GLfloat light_specular [ 4 ] ;
glGetLightfv ( GL_LIGHT1 , GL_AMBIENT , light_ambient ) ;
glGetLightfv ( GL_LIGHT1 , GL_DIFFUSE , light_diffuse ) ;
glGetLightfv ( GL_LIGHT1 , GL_SPECULAR , light_specular ) ;
NSLog ( @ "OPENGL_DEBUG GL_LIGHT1 GL_AMBIENT ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
light_ambient [ 0 ] , light_ambient [ 1 ] , light_ambient [ 2 ] , light_ambient [ 3 ] ) ;
NSLog ( @ "OPENGL_DEBUG GL_LIGHT1 GL_DIFFUSE ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
light_diffuse [ 0 ] , light_diffuse [ 1 ] , light_diffuse [ 2 ] , light_diffuse [ 3 ] ) ;
NSLog ( @ "OPENGL_DEBUG GL_LIGHT1 GL_SPECULAR ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
light_specular [ 0 ] , light_specular [ 1 ] , light_specular [ 2 ] , light_specular [ 3 ] ) ;
}
if ( glIsEnabled ( GL_LIGHT2 ) )
NSLog ( @ "OPENGL_DEBUG GL_LIGHT2 :ENABLED:" ) ;
if ( glIsEnabled ( GL_LIGHT3 ) )
NSLog ( @ "OPENGL_DEBUG GL_LIGHT3 :ENABLED:" ) ;
if ( glIsEnabled ( GL_LIGHT4 ) )
NSLog ( @ "OPENGL_DEBUG GL_LIGHT4 :ENABLED:" ) ;
if ( glIsEnabled ( GL_LIGHT5 ) )
NSLog ( @ "OPENGL_DEBUG GL_LIGHT5 :ENABLED:" ) ;
if ( glIsEnabled ( GL_LIGHT6 ) )
NSLog ( @ "OPENGL_DEBUG GL_LIGHT6 :ENABLED:" ) ;
if ( glIsEnabled ( GL_LIGHT7 ) )
NSLog ( @ "OPENGL_DEBUG GL_LIGHT7 :ENABLED:" ) ;
}
/ * - - LIGHTS - - * /
NSLog ( @ "OPENGL_DEBUG GL_CURRENT_COLOR ( %.2ff, %.2ff, %.2ff, %.2ff)" ,
current_color [ 0 ] , current_color [ 1 ] , current_color [ 2 ] , current_color [ 3 ] ) ;
//
NSLog ( @ "OPENGL_DEBUG GL_TEXTURE_ENV_MODE :%@:" , tex_env _mode _string ) ;
//
NSLog ( @ "OPENGL_DEBUG GL_SHADEMODEL :%@:" , ( gl_shade _model [ 0 ] = = GL_SMOOTH ) ? @ "GL_SMOOTH" : @ "GL_FLAT" ) ;
//
if ( glIsEnabled ( GL_FOG ) )
NSLog ( @ "OPENGL_DEBUG GL_FOG :ENABLED:" ) ;
//
if ( glIsEnabled ( GL_COLOR _MATERIAL ) )
NSLog ( @ "OPENGL_DEBUG GL_COLOR_MATERIAL :ENABLED:" ) ;
//
if ( glIsEnabled ( GL_BLEND ) )
{
NSLog ( @ "OPENGL_DEBUG GL_BLEND :ENABLED:" ) ;
NSLog ( @ "OPENGL_DEBUG GL_BLEND_FUNC (:%@:, :%@:)" , blend_src _string , blend_dst _string ) ;
}
//
if ( glIsEnabled ( GL_CULL _FACE ) )
NSLog ( @ "OPENGL_DEBUG GL_CULL_FACE :ENABLED:" ) ;
//
NSLog ( @ "OPENGL_DEBUG GL_CULL_FACE_MODE :%@:" , cull_face _mode _string ) ;
//
NSLog ( @ "OPENGL_DEBUG GL_FRONT_FACE :%@:" , front_face _string ) ;
}
// check for OpenGL errors , reporting them if where is not nil
//
BOOL checkGLErrors ( NSString * where )
{
GLenum errCode ;
const GLubyte * errString ;
if ( ( errCode = glGetError ( ) ) ! = GL_NO _ERROR )
{
errString = gluErrorString ( errCode ) ;
if ( where )
NSLog ( @ "OPENGL_DEBUG GL_ERROR (%d) '%s' in: %@" , errCode , errString , where ) ;
return YES ;
}
return NO ;
}
// keep track of various OpenGL states
//
void my_glEnable ( GLenum gl_state )
{
switch ( gl_state )
{
case GL_TEXTURE _2D :
if ( mygl_texture _2d )
return ;
mygl_texture _2d = YES ;
break ;
default :
break ;
}
glEnable ( gl_state ) ;
}
//
void my_glDisable ( GLenum gl_state )
{
switch ( gl_state )
{
case GL_TEXTURE _2D :
if ( ! mygl_texture _2d )
return ;
mygl_texture _2d = NO ;
break ;
default :
break ;
}
glDisable ( gl_state ) ;
}
2005-04-19 19:53:18 +00:00
@ end