Incomplete support for general polygons in missile icons. (In case of splodey, setting the OLD_ICONS macro in HeadUpDisplay.m to 1 will revert to the old drawing code.)
git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2661 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
parent
e1ea90a110
commit
bc3a113b0f
@ -139,7 +139,8 @@ OOLITE_GRAPHICS_MISC_FILES = \
|
||||
OOOpenGLExtensionManager.m \
|
||||
OOProbabilisticTextureManager.m \
|
||||
OOSkyDrawable.m \
|
||||
OpenGLSprite.m
|
||||
OpenGLSprite.m \
|
||||
OOPolygonSprite.m
|
||||
|
||||
OOLITE_MATHS_FILES = \
|
||||
CollisionRegion.m \
|
||||
|
@ -564,6 +564,8 @@
|
||||
1AB812900E90179D00A84923 /* TextureStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 25161134099544390037C2E1 /* TextureStore.h */; };
|
||||
1AB813090E90D8E500A84923 /* OOLogOutputHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AB813070E90D8E500A84923 /* OOLogOutputHandler.m */; };
|
||||
1AB8130A0E90D8E500A84923 /* OOLogOutputHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB813080E90D8E500A84923 /* OOLogOutputHandler.h */; };
|
||||
1AB9AE8B107F459B00B6F3CE /* OOPolygonSprite.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB9AE89107F459B00B6F3CE /* OOPolygonSprite.h */; };
|
||||
1AB9AE8C107F459B00B6F3CE /* OOPolygonSprite.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AB9AE8A107F459B00B6F3CE /* OOPolygonSprite.m */; };
|
||||
1ABAD7310F350B3400FD2CBF /* OOShipGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ABAD72F0F350B3400FD2CBF /* OOShipGroup.m */; };
|
||||
1ABAD7320F350B3400FD2CBF /* OOShipGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ABAD7300F350B3400FD2CBF /* OOShipGroup.h */; };
|
||||
1ABB688C0D044306008BE96D /* OOLoggingExtended.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ABB688B0D044306008BE96D /* OOLoggingExtended.h */; };
|
||||
@ -1652,6 +1654,8 @@
|
||||
1AB784F80D554F7B00517983 /* OOJSSoundSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOJSSoundSource.m; sourceTree = "<group>"; };
|
||||
1AB813070E90D8E500A84923 /* OOLogOutputHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOLogOutputHandler.m; sourceTree = "<group>"; };
|
||||
1AB813080E90D8E500A84923 /* OOLogOutputHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOLogOutputHandler.h; sourceTree = "<group>"; };
|
||||
1AB9AE89107F459B00B6F3CE /* OOPolygonSprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOPolygonSprite.h; sourceTree = "<group>"; };
|
||||
1AB9AE8A107F459B00B6F3CE /* OOPolygonSprite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOPolygonSprite.m; sourceTree = "<group>"; };
|
||||
1ABAD72F0F350B3400FD2CBF /* OOShipGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOShipGroup.m; sourceTree = "<group>"; };
|
||||
1ABAD7300F350B3400FD2CBF /* OOShipGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOShipGroup.h; sourceTree = "<group>"; };
|
||||
1ABB688B0D044306008BE96D /* OOLoggingExtended.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOLoggingExtended.h; sourceTree = "<group>"; };
|
||||
@ -2224,6 +2228,8 @@
|
||||
1A94D5B40D65A6B40072C805 /* OOCamera.m */,
|
||||
25161100099544380037C2E1 /* OpenGLSprite.h */,
|
||||
251610FF099544380037C2E1 /* OpenGLSprite.m */,
|
||||
1AB9AE89107F459B00B6F3CE /* OOPolygonSprite.h */,
|
||||
1AB9AE8A107F459B00B6F3CE /* OOPolygonSprite.m */,
|
||||
1AED2D0A0C04586C004A1118 /* OOGraphicsResetManager.h */,
|
||||
1AED2D0B0C04586C004A1118 /* OOGraphicsResetManager.m */,
|
||||
1ADC3F850BFA1388000E0F89 /* Drawables */,
|
||||
@ -3112,6 +3118,7 @@
|
||||
1A817DA0106D3FF000AA2F97 /* OOPlasmaBurstEntity.h in Headers */,
|
||||
1A817DC3106D443B00AA2F97 /* OOFlashEffectEntity.h in Headers */,
|
||||
2B4CDFEC107B3D8400526C98 /* OOJSManifest.h in Headers */,
|
||||
1AB9AE8B107F459B00B6F3CE /* OOPolygonSprite.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -3463,6 +3470,7 @@
|
||||
1A817DA1106D3FF000AA2F97 /* OOPlasmaBurstEntity.m in Sources */,
|
||||
1A817DC4106D443B00AA2F97 /* OOFlashEffectEntity.m in Sources */,
|
||||
2B4CDFED107B3D8400526C98 /* OOJSManifest.m in Sources */,
|
||||
1AB9AE8C107F459B00B6F3CE /* OOPolygonSprite.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -731,6 +731,63 @@
|
||||
-2, -3,
|
||||
-2, 1
|
||||
);
|
||||
"oolite-default-missile-icon" =
|
||||
(
|
||||
0, 3,
|
||||
2, 0,
|
||||
1, 0,
|
||||
1, -2,
|
||||
-1, -2,
|
||||
-1, 0,
|
||||
-2, 0
|
||||
);
|
||||
// The following is a test of a complex, multi-contour polygon sprite
|
||||
// with non-overlapping contours. It also happens to generate a mix of
|
||||
// triangle strips and individual triangles. (The default icon generates
|
||||
// a single triangle fan.)
|
||||
// -- Ahruman 2009-10-10
|
||||
/* (
|
||||
(
|
||||
-1, 2,
|
||||
1, 2,
|
||||
1, -2,
|
||||
-1, -2
|
||||
),
|
||||
(
|
||||
-3, 3,
|
||||
3, 3,
|
||||
3, -3,
|
||||
-3, -3
|
||||
)
|
||||
);*/
|
||||
// The following is a test of a complex, multi-contour polygon sprite
|
||||
// which self-intersects.
|
||||
// It currently doesn't work, because it requires a combine callback.
|
||||
// -- Ahruman 2009-10-10
|
||||
/* (
|
||||
(
|
||||
-1, 3,
|
||||
1, 3,
|
||||
1, -2,
|
||||
-1, -2
|
||||
),
|
||||
(
|
||||
-3, 1,
|
||||
3, 1,
|
||||
3, -3,
|
||||
-3, -3
|
||||
)
|
||||
);
|
||||
*/
|
||||
"oolite-default-mine-icon" =
|
||||
(
|
||||
0, 2,
|
||||
1, 1,
|
||||
1, -1,
|
||||
0, -2,
|
||||
-1, -1,
|
||||
-1, 1
|
||||
);
|
||||
// human surname namegen
|
||||
"nom" =
|
||||
(
|
||||
|
@ -76,6 +76,13 @@ mission.runMissionScreen = function (messageKey, backgroundImage, choiceKey, shi
|
||||
};
|
||||
|
||||
|
||||
// mission.addMessageTextKey(): load mission text from mission.plist and append to mission screen or info screen.
|
||||
mission.addMessageTextKey = function(textKey)
|
||||
{
|
||||
mission.addMessageText(expandMissionText(textKey));
|
||||
}
|
||||
|
||||
|
||||
/* string.trim(): remove leading and trailing whitespace.
|
||||
Implementation by Steve Leviathan, see:
|
||||
http://blog.stevenlevithan.com/archives/faster-trim-javascript
|
||||
|
@ -312,6 +312,9 @@ GLuint tfan2[10] = { 33, 25, 26, 27, 28, 29, 30, 31, 32, 25 }; // final fan 6
|
||||
OOGL(glDrawElements(GL_QUAD_STRIP, 18, GL_UNSIGNED_INT, qstrip3));
|
||||
OOGL(glDrawElements(GL_TRIANGLE_FAN, 10, GL_UNSIGNED_INT, tfan2));
|
||||
|
||||
OOGL(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
OOGL(glDisableClientState(GL_COLOR_ARRAY));
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
|
@ -1179,7 +1179,6 @@ static float corona_blending;
|
||||
OOGL(glNormalPointer(GL_FLOAT, 0, vertexdata.normal_array));
|
||||
|
||||
OOGL(glCallList(displayListNames[subdivideLevel]));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1311,6 +1310,11 @@ static float corona_blending;
|
||||
{
|
||||
GLDebugWireframeModeOff();
|
||||
}
|
||||
|
||||
OOGL(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
OOGL(glDisableClientState(GL_NORMAL_ARRAY));
|
||||
OOGL(glDisableClientState(GL_COLOR_ARRAY));
|
||||
OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
break;
|
||||
|
||||
case PLANET_TYPE_SUN:
|
||||
|
@ -142,7 +142,10 @@ Ringdata ringentity;
|
||||
OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
OOGL(glDisableClientState(GL_EDGE_FLAG_ARRAY));
|
||||
|
||||
OOGL(glDrawElements( GL_TRIANGLES, 3 * 64, GL_UNSIGNED_INT, ringentity.triangle_index_array));
|
||||
OOGL(glDrawElements(GL_TRIANGLES, 3 * 64, GL_UNSIGNED_INT, ringentity.triangle_index_array));
|
||||
|
||||
OOGL(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
OOGL(glDisableClientState(GL_COLOR_ARRAY));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -207,7 +207,7 @@ MA 02110-1301, USA.
|
||||
AI *shipAI; // ship's AI system
|
||||
|
||||
NSString *name; // descriptive name
|
||||
NSString *displayName; // name shown on screen
|
||||
NSString *displayName; // name shown on screen
|
||||
OORoleSet *roleSet; // Roles a ship can take, eg. trader, hunter, police, pirate, scavenger &c.
|
||||
NSString *primaryRole; // "Main" role of the ship.
|
||||
|
||||
|
@ -33,6 +33,7 @@ MA 02110-1301, USA.
|
||||
#import "GuiDisplayGen.h"
|
||||
#import "OOTexture.h"
|
||||
#import "OpenGLSprite.h"
|
||||
#import "OOPolygonSprite.h"
|
||||
#import "OOCollectionExtractors.h"
|
||||
#import "OOEncodingConverter.h"
|
||||
#import "OOCrosshairs.h"
|
||||
@ -41,6 +42,9 @@ MA 02110-1301, USA.
|
||||
#import "JoystickHandler.h"
|
||||
|
||||
|
||||
#define OLD_ICONS 0
|
||||
|
||||
|
||||
#define kOOLogUnconvertedNSLog @"unclassified.HeadUpDisplay"
|
||||
|
||||
|
||||
@ -58,7 +62,9 @@ static void hudDrawMarkerAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, double
|
||||
static void hudDrawBarAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, double amount);
|
||||
static void hudDrawSurroundAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz);
|
||||
static void hudDrawSpecialIconAt(NSArray* ptsArray, int x, int y, int z, NSSize siz);
|
||||
#if OLD_ICONS
|
||||
static void hudDrawMineIconAt(int x, int y, int z, NSSize siz);
|
||||
#endif
|
||||
static void hudDrawMissileIconAt(int x, int y, int z, NSSize siz);
|
||||
static void hudDrawStatusIconAt(int x, int y, int z, NSSize siz);
|
||||
static void hudDrawReticleOnTarget(Entity* target, PlayerEntity* player1, GLfloat z1, GLfloat overallAlpha, BOOL reticleTargetSensitive);
|
||||
@ -371,6 +377,8 @@ OOINLINE void GLColorWithOverallAlpha(GLfloat *color, GLfloat alpha)
|
||||
|
||||
- (void) renderHUD
|
||||
{
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
OOGL(glLineWidth(_crosshairWidth * line_width));
|
||||
[self drawCrosshairs];
|
||||
|
||||
@ -1505,6 +1513,103 @@ OOINLINE void SetCompassBlipColor(GLfloat relativeZ, GLfloat alpha)
|
||||
}
|
||||
|
||||
|
||||
#if !OLD_ICONS
|
||||
|
||||
static NSString * const kDefaultMissileIconKey = @"oolite-default-missile-icon";
|
||||
static NSString * const kDefaultMineIconKey = @"oolite-default-mine-icon";
|
||||
|
||||
|
||||
static OOPolygonSprite *IconForMissileRole(NSString *role)
|
||||
{
|
||||
static NSMutableDictionary *sIcons = nil;
|
||||
OOPolygonSprite *result = nil;
|
||||
|
||||
result = [sIcons objectForKey:role];
|
||||
if (result == nil)
|
||||
{
|
||||
NSString *key = role;
|
||||
NSArray *iconDef = [[UNIVERSE descriptions] oo_arrayForKey:key];
|
||||
if (iconDef != nil) result = [[OOPolygonSprite alloc] initWithDataArray:iconDef outlineWidth:0.5f name:key];
|
||||
if (result == nil) // No custom icon or bad data
|
||||
{
|
||||
/* Backwards compatibility note:
|
||||
The old implementation used suffixes "MISSILE" and "MINE" (without
|
||||
the underscore), and didn't draw anything if neither was found. I
|
||||
believe any difference in practical behavour due to the change here
|
||||
will be positive.
|
||||
-- Ahruman 2009-10-09
|
||||
*/
|
||||
if ([role hasSuffix:@"_MISSILE"]) key = kDefaultMissileIconKey;
|
||||
else key = kDefaultMineIconKey;
|
||||
|
||||
iconDef = [[UNIVERSE descriptions] oo_arrayForKey:key];
|
||||
result = [[OOPolygonSprite alloc] initWithDataArray:iconDef outlineWidth:0.5f name:key];
|
||||
}
|
||||
|
||||
if (result != nil)
|
||||
{
|
||||
if (sIcons == nil) sIcons = [[NSMutableDictionary alloc] init];
|
||||
[sIcons setObject:result forKey:role];
|
||||
[result release]; // Balance alloc
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (void) drawIconForMissile:(ShipEntity *)missile
|
||||
selected:(BOOL)selected
|
||||
status:(OOMissileStatus)status
|
||||
x:(int)x y:(int)y
|
||||
width:(GLfloat)width height:(GLfloat)height
|
||||
{
|
||||
OOPolygonSprite *sprite = IconForMissileRole([missile primaryRole]);
|
||||
|
||||
if (selected)
|
||||
{
|
||||
// Draw yellow outline.
|
||||
OOGL(glPushMatrix());
|
||||
OOGL(glTranslatef(x - width * 2.0f, y - height * 2.0f, z1));
|
||||
OOGL(glScalef(width + 1.0f, height + 1.0f, 1.0f));
|
||||
GLColorWithOverallAlpha(yellow_color, overallAlpha);
|
||||
[sprite drawFilled];
|
||||
OOGL(glPopMatrix());
|
||||
|
||||
// Draw black backing, so outline colour isn’t blended into missile colour.
|
||||
OOGL(glPushMatrix());
|
||||
OOGL(glTranslatef(x - width * 2.0f, y - height * 2.0f, z1));
|
||||
OOGL(glScalef(width, height, 1.0f));
|
||||
GLColorWithOverallAlpha(black_color, overallAlpha);
|
||||
[sprite drawFilled];
|
||||
OOGL(glPopMatrix());
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case MISSILE_STATUS_SAFE :
|
||||
GLColorWithOverallAlpha(green_color, overallAlpha); break;
|
||||
case MISSILE_STATUS_ARMED :
|
||||
GLColorWithOverallAlpha(yellow_color, overallAlpha); break;
|
||||
case MISSILE_STATUS_TARGET_LOCKED :
|
||||
GLColorWithOverallAlpha(red_color, overallAlpha); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([missile primaryTarget] == nil) GLColorWithOverallAlpha(green_color, overallAlpha);
|
||||
else GLColorWithOverallAlpha(red_color, overallAlpha);
|
||||
}
|
||||
|
||||
OOGL(glPushMatrix());
|
||||
OOGL(glTranslatef(x - width * 2.0f, y - height * 2.0f, z1));
|
||||
OOGL(glScalef(width, height, 1.0f));
|
||||
[sprite drawFilled];
|
||||
OOGL(glPopMatrix());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
- (void) drawMissileDisplay:(NSDictionary *) info
|
||||
{
|
||||
PlayerEntity *player = [PlayerEntity sharedPlayer];
|
||||
@ -1521,14 +1626,23 @@ OOINLINE void SetCompassBlipColor(GLfloat relativeZ, GLfloat alpha)
|
||||
|
||||
if (![player dialIdentEngaged])
|
||||
{
|
||||
OOMissileStatus status = [player dialMissileStatus];
|
||||
unsigned n_mis = [player dialMaxMissiles];
|
||||
unsigned i;
|
||||
for (i = 0; i < n_mis; i++)
|
||||
{
|
||||
if ([player missileForStation:i])
|
||||
ShipEntity *missile = [player missileForStation:i];
|
||||
if (missile)
|
||||
{
|
||||
#if !OLD_ICONS
|
||||
[self drawIconForMissile:missile
|
||||
selected:i == [player activeMissile]
|
||||
status:status
|
||||
x:x + (int)i * sp + 2 y:y
|
||||
width:siz.width *0.25f height:siz.height *0.25f];
|
||||
#else
|
||||
// TODO: copy icon data into missile object instead of looking it up each time. Possibly make weapon stores a ShipEntity subclass?
|
||||
NSString *miss_roles = [[player missileForStation:i] primaryRole];
|
||||
NSString *miss_roles = [missile primaryRole];
|
||||
NSArray *miss_icon = [[UNIVERSE descriptions] oo_arrayForKey:miss_roles];
|
||||
if (i == [player activeMissile])
|
||||
{
|
||||
@ -1575,7 +1689,7 @@ OOINLINE void SetCompassBlipColor(GLfloat relativeZ, GLfloat alpha)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([[player missileForStation:i] primaryTarget])
|
||||
if ([missile primaryTarget])
|
||||
GLColorWithOverallAlpha(red_color, overallAlpha);
|
||||
else
|
||||
GLColorWithOverallAlpha(green_color, overallAlpha);
|
||||
@ -1610,9 +1724,10 @@ OOINLINE void SetCompassBlipColor(GLfloat relativeZ, GLfloat alpha)
|
||||
}
|
||||
OOGLEND();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
GLColorWithOverallAlpha(lightgray_color, overallAlpha);
|
||||
OOGLBEGIN(GL_LINE_LOOP);
|
||||
hudDrawMissileIconAt(x + i * sp, y, z1, siz);
|
||||
@ -2123,9 +2238,9 @@ static void hudDrawSpecialIconAt(NSArray* ptsArray, int x, int y, int z, NSSize
|
||||
int ox = x - siz.width / 2.0;
|
||||
int oy = y - siz.height / 2.0;
|
||||
int w = siz.width / 4.0;
|
||||
int h = siz.height / 4.0;
|
||||
int h = siz.height / 4.0;
|
||||
int i = 0;
|
||||
int npts = [ptsArray count] & 0xfffe; // make sure it's an even number
|
||||
int npts = [ptsArray count] & ~1; // make sure it's an even number
|
||||
while (i < npts)
|
||||
{
|
||||
int x = [ptsArray oo_intAtIndex:i++];
|
||||
@ -2142,16 +2257,17 @@ static void hudDrawMissileIconAt(int x, int y, int z, NSSize siz)
|
||||
int w = siz.width / 4.0;
|
||||
int h = siz.height / 4.0;
|
||||
|
||||
glVertex3i(ox, oy + 3 * h, z);
|
||||
glVertex3i(ox + 2 * w, oy, z);
|
||||
glVertex3i(ox + w, oy, z);
|
||||
glVertex3i(ox + w, oy - 2 * h, z);
|
||||
glVertex3i(ox - w, oy - 2 * h, z);
|
||||
glVertex3i(ox - w, oy, z);
|
||||
glVertex3i(ox - 2 * w, oy, z);
|
||||
glVertex3i(ox + 0 * w, oy + 3 * h, z);
|
||||
glVertex3i(ox + 2 * w, oy + 0 * h, z);
|
||||
glVertex3i(ox + 1 * w, oy + 0 * h, z);
|
||||
glVertex3i(ox + 1 * w, oy - 2 * h, z);
|
||||
glVertex3i(ox - 1 * w, oy - 2 * h, z);
|
||||
glVertex3i(ox - 1 * w, oy + 0 * h, z);
|
||||
glVertex3i(ox - 2 * w, oy + 0 * h, z);
|
||||
}
|
||||
|
||||
|
||||
#if OLD_ICONS
|
||||
static void hudDrawMineIconAt(int x, int y, int z, NSSize siz)
|
||||
{
|
||||
int ox = x - siz.width / 2.0;
|
||||
@ -2159,13 +2275,14 @@ static void hudDrawMineIconAt(int x, int y, int z, NSSize siz)
|
||||
int w = siz.width / 4.0;
|
||||
int h = siz.height / 4.0;
|
||||
|
||||
glVertex3i(ox, oy + 2 * h, z);
|
||||
glVertex3i(ox + w, oy + h, z);
|
||||
glVertex3i(ox + w, oy - h, z);
|
||||
glVertex3i(ox, oy - 2 * h, z);
|
||||
glVertex3i(ox - w, oy - h, z);
|
||||
glVertex3i(ox - w, oy + h, z);
|
||||
glVertex3i(ox + 0 * w, oy + 2 * h, z);
|
||||
glVertex3i(ox + 1 * w, oy + 1 * h, z);
|
||||
glVertex3i(ox + 1 * w, oy - 1 * h, z);
|
||||
glVertex3i(ox + 0 * w, oy - 2 * h, z);
|
||||
glVertex3i(ox - 1 * w, oy - 1 * h, z);
|
||||
glVertex3i(ox - 1 * w, oy + 1 * h, z);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void hudDrawStatusIconAt(int x, int y, int z, NSSize siz)
|
||||
|
@ -78,6 +78,9 @@
|
||||
|
||||
OOGL(glDrawArrays(GL_LINES, 0, _count * 2));
|
||||
|
||||
OOGL(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
OOGL(glDisableClientState(GL_COLOR_ARRAY));
|
||||
|
||||
OOGL(glPopMatrix());
|
||||
OOGL(glPopAttrib());
|
||||
}
|
||||
|
@ -306,6 +306,10 @@ shaderBindingTarget:(id<OOWeakReferenceSupport>)object
|
||||
else [localException raise]; // pass these on
|
||||
NS_ENDHANDLER
|
||||
|
||||
OOGL(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
OOGL(glDisableClientState(GL_NORMAL_ARRAY));
|
||||
OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (gDebugFlags & DEBUG_DRAW_NORMALS) [self debugDrawNormals];
|
||||
#endif
|
||||
|
57
src/Core/OOPolygonSprite.h
Normal file
57
src/Core/OOPolygonSprite.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
|
||||
OOPolygonSprite.h
|
||||
Oolite
|
||||
|
||||
Two-dimensional polygon object for UI things such as missile icons.
|
||||
|
||||
|
||||
Copyright (C) 2009 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#import "OOCocoa.h"
|
||||
#import "OOOpenGL.h"
|
||||
|
||||
|
||||
@interface OOPolygonSprite: NSObject
|
||||
{
|
||||
@private
|
||||
GLfloat *_solidData;
|
||||
size_t _solidCount;
|
||||
|
||||
#ifndef NDEBUG
|
||||
NSString *_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* DataArray is either an array of pairs of numbers, or an array of such
|
||||
arrays (representing one or more contours).
|
||||
OutlineWidth is the width of the tesselated outline, in the same scale as
|
||||
the vertices.
|
||||
Name is used for debugging only.
|
||||
*/
|
||||
- (id) initWithDataArray:(NSArray *)dataArray outlineWidth:(GLfloat)outlineWidth name:(NSString *)name;
|
||||
|
||||
- (void) drawFilled;
|
||||
|
||||
@end
|
403
src/Core/OOPolygonSprite.m
Normal file
403
src/Core/OOPolygonSprite.m
Normal file
@ -0,0 +1,403 @@
|
||||
/*
|
||||
|
||||
OOPolygonSprite.m
|
||||
Oolite
|
||||
|
||||
|
||||
Copyright (C) 2009 Jens Ayton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
/* Implementation note:
|
||||
|
||||
The polygon data is tesselated (on object creation) using a GLU tesselator.
|
||||
Although GLU produces a mix of triangles, triangle fans and triangle
|
||||
strips, we convert those to a single triangle soup since the primitives are
|
||||
unlikely to be large enough that using multiple primitives would be a win.
|
||||
|
||||
Uniquing vertices and using indices, and using the same vertex array for
|
||||
outline and filled mode, would in principle be more efficient, but not
|
||||
worth the added complexity in the preprocessing given the simplicity of
|
||||
the icons we're likely to encounter.
|
||||
*/
|
||||
|
||||
#undef OO_CHECK_GL_HEAVY
|
||||
#define OO_CHECK_GL_HEAVY 0
|
||||
|
||||
#import "OOPolygonSprite.h"
|
||||
#import "OOCollectionExtractors.h"
|
||||
#import "OOMacroOpenGL.h"
|
||||
|
||||
|
||||
#define TESS_TOLERANCE 0.05 // Feature merging factor: higher values merge more features with greater chance of distortion.
|
||||
|
||||
|
||||
@interface OOPolygonSprite (Private)
|
||||
|
||||
- (BOOL) loadPolygons:(NSArray *)dataArray;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GLfloat *data;
|
||||
size_t count; // Number of vertices in use, i.e. half of number of data elements used.
|
||||
size_t capacity; // Half of number of floats there is space for in data.
|
||||
GLenum mode; // Current primitive mode.
|
||||
size_t vCount; // Number of vertices so far in primitive.
|
||||
NSPoint pending0, pending1; // Used for splitting GL_TRIANGLE_STRIP/GL_TRIANGLE_FAN primitives.
|
||||
BOOL OK; // Set to false to indicate error.
|
||||
#ifndef NDEBUG
|
||||
NSString *name;
|
||||
#endif
|
||||
} TessPolygonData;
|
||||
|
||||
|
||||
static BOOL GrowTessPolygonData(TessPolygonData *data, size_t capacityHint); // Returns true if capacity grew by at least one.
|
||||
static BOOL AppendVertex(TessPolygonData *data, NSPoint vertex);
|
||||
|
||||
|
||||
static void SolidBeginCallback(GLenum type, void *polygonData);
|
||||
static void SolidVertexCallback(void *vertexData, void *polygonData);
|
||||
static void SolidEndCallback(void *polygonData);
|
||||
|
||||
static void ErrorCallback(GLenum error, void *polygonData);
|
||||
|
||||
|
||||
@implementation OOPolygonSprite
|
||||
|
||||
- (id) initWithDataArray:(NSArray *)dataArray outlineWidth:(GLfloat)outlineWidth name:(NSString *)name
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
_name = [name copy];
|
||||
#endif
|
||||
|
||||
if ([dataArray count] == 0)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Normalize data to array-of-arrays form.
|
||||
if (![[dataArray objectAtIndex:0] isKindOfClass:[NSArray class]])
|
||||
{
|
||||
dataArray = [NSArray arrayWithObject:dataArray];
|
||||
}
|
||||
if (![self loadPolygons:dataArray])
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
DESTROY(_name);
|
||||
#endif
|
||||
|
||||
free(_solidData);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
- (NSString *) descriptionComponents
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
- (void) drawFilled
|
||||
{
|
||||
OO_ENTER_OPENGL();
|
||||
|
||||
OOGL(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
OOGL(glVertexPointer(2, GL_FLOAT, 0, _solidData));
|
||||
OOGL(glDrawArrays(GL_TRIANGLES, 0, _solidCount));
|
||||
OOGL(glDisableClientState(GL_VERTEX_ARRAY));
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) loadPolygons:(NSArray *)dataArray
|
||||
{
|
||||
NSParameterAssert(dataArray != nil);
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
GLUtesselator *tesselator = NULL;
|
||||
|
||||
TessPolygonData polygonData;
|
||||
memset(&polygonData, 0, sizeof polygonData);
|
||||
polygonData.OK = YES;
|
||||
#ifndef NDEBUG
|
||||
polygonData.name = _name;
|
||||
#endif
|
||||
#if !OO_DEBUG
|
||||
// For efficiency, grow to more than big enough for most cases to avoid regrowing.
|
||||
if (!GrowTessPolygonData(&polygonData, 100))
|
||||
{
|
||||
polygonData.OK = NO;
|
||||
goto END;
|
||||
}
|
||||
#endif
|
||||
|
||||
tesselator = gluNewTess();
|
||||
if (tesselator == NULL)
|
||||
{
|
||||
polygonData.OK = NO;
|
||||
goto END;
|
||||
}
|
||||
|
||||
gluTessCallback(tesselator, GLU_TESS_BEGIN_DATA, SolidBeginCallback);
|
||||
gluTessCallback(tesselator, GLU_TESS_VERTEX_DATA, SolidVertexCallback);
|
||||
gluTessCallback(tesselator, GLU_TESS_END_DATA, SolidEndCallback);
|
||||
gluTessCallback(tesselator, GLU_TESS_ERROR_DATA, ErrorCallback);
|
||||
gluTessProperty(tesselator, GLU_TESS_TOLERANCE, TESS_TOLERANCE);
|
||||
|
||||
gluTessBeginPolygon(tesselator, &polygonData);
|
||||
|
||||
OOUInteger contourCount = [dataArray count], contourIndex;
|
||||
for (contourIndex = 0; contourIndex < contourCount && polygonData.OK; contourIndex++)
|
||||
{
|
||||
NSArray *contour = [dataArray oo_arrayAtIndex:contourIndex];
|
||||
if (contour == nil)
|
||||
{
|
||||
polygonData.OK = NO;
|
||||
break;
|
||||
}
|
||||
|
||||
OOUInteger vertexCount = [contour count] / 2, vertexIndex;
|
||||
if (vertexCount > 2)
|
||||
{
|
||||
gluTessBeginContour(tesselator);
|
||||
|
||||
for (vertexIndex = 0; vertexIndex < vertexCount && polygonData.OK; vertexIndex++)
|
||||
{
|
||||
GLdouble vert[3] =
|
||||
{
|
||||
[contour oo_doubleAtIndex:vertexIndex * 2],
|
||||
[contour oo_doubleAtIndex:vertexIndex * 2 + 1],
|
||||
0.0
|
||||
};
|
||||
|
||||
/* The third parameter to gluTessVertex() is the data
|
||||
actually passed to our vertex callback. Since the vertex
|
||||
callback isn't called until later, each vertex's data needs
|
||||
to have an independent existence. We pack them into
|
||||
NSValues here and let NSAutoReleasepool clean up
|
||||
afterwards.
|
||||
*/
|
||||
NSPoint p = { vert[0], vert[1] };
|
||||
NSValue *vertValue = [NSValue valueWithPoint:p];
|
||||
gluTessVertex(tesselator, vert, vertValue);
|
||||
}
|
||||
|
||||
gluTessEndContour(tesselator);
|
||||
}
|
||||
}
|
||||
|
||||
gluTessEndPolygon(tesselator);
|
||||
|
||||
if (polygonData.OK)
|
||||
{
|
||||
_solidCount = polygonData.count;
|
||||
_solidData = realloc(polygonData.data, polygonData.count * sizeof (GLfloat) * 2);
|
||||
if (_solidData != NULL) polygonData.data = NULL;
|
||||
else
|
||||
{
|
||||
_solidData = polygonData.data;
|
||||
if (_solidData == NULL) polygonData.OK = NO;
|
||||
}
|
||||
}
|
||||
|
||||
END:
|
||||
free(polygonData.data);
|
||||
gluDeleteTess(tesselator);
|
||||
[pool release];
|
||||
return polygonData.OK;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static BOOL GrowTessPolygonData(TessPolygonData *data, size_t capacityHint)
|
||||
{
|
||||
NSCParameterAssert(data != NULL);
|
||||
|
||||
size_t minCapacity = data->capacity + 1;
|
||||
size_t desiredCapacity = MAX(capacityHint, minCapacity);
|
||||
size_t newCapacity = 0;
|
||||
GLfloat *newData = realloc(data->data, desiredCapacity * sizeof (GLfloat) * 2);
|
||||
if (newData != NULL)
|
||||
{
|
||||
newCapacity = desiredCapacity;
|
||||
}
|
||||
else
|
||||
{
|
||||
desiredCapacity = minCapacity;
|
||||
newData = realloc(data->data, desiredCapacity * sizeof (GLfloat) * 2);
|
||||
if (newData != NULL) newCapacity = desiredCapacity;
|
||||
}
|
||||
|
||||
if (newData == NULL) return NO;
|
||||
|
||||
NSCAssert(newCapacity > data->capacity, @"Buffer regrow logic error");
|
||||
|
||||
data->data = newData;
|
||||
data->capacity = newCapacity;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
static BOOL AppendVertex(TessPolygonData *data, NSPoint vertex)
|
||||
{
|
||||
NSCParameterAssert(data != NULL);
|
||||
|
||||
if (data->capacity == data->count && !GrowTessPolygonData(data, data->capacity * 2)) return NO;
|
||||
|
||||
data->data[data->count * 2] = vertex.x;
|
||||
data->data[data->count * 2 + 1] = vertex.y;
|
||||
data->count++;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
static void SolidBeginCallback(GLenum type, void *polygonData)
|
||||
{
|
||||
TessPolygonData *data = polygonData;
|
||||
NSCParameterAssert(data != NULL);
|
||||
|
||||
data->mode = type;
|
||||
data->vCount = 0;
|
||||
}
|
||||
|
||||
|
||||
static void SolidVertexCallback(void *vertexData, void *polygonData)
|
||||
{
|
||||
TessPolygonData *data = polygonData;
|
||||
NSValue *vertValue = vertexData;
|
||||
NSCParameterAssert(vertValue != NULL && data != NULL);
|
||||
if (!data->OK) return;
|
||||
|
||||
NSPoint p = [vertValue pointValue];
|
||||
NSPoint vertex = { p.x, p.y };
|
||||
size_t vCount = data->vCount++;
|
||||
|
||||
switch (data->mode)
|
||||
{
|
||||
case GL_TRIANGLES:
|
||||
data->OK = AppendVertex(data, vertex);
|
||||
OOLog(@"tesselate.vertex.tri", @"%u: %@", vCount, NSStringFromPoint(vertex));
|
||||
break;
|
||||
|
||||
case GL_TRIANGLE_FAN:
|
||||
if (vCount == 0) data->pending0 = vertex;
|
||||
else if (vCount == 1) data->pending1 = vertex;
|
||||
else
|
||||
{
|
||||
data->OK = AppendVertex(data, data->pending0) &&
|
||||
AppendVertex(data, data->pending1) &&
|
||||
AppendVertex(data, vertex);
|
||||
OOLog(@"tesselate.vertex.fan", @"%u: (%@ %@) %@", vCount, NSStringFromPoint(data->pending0), NSStringFromPoint(data->pending1), NSStringFromPoint(vertex));
|
||||
data->pending1 = vertex;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TRIANGLE_STRIP:
|
||||
if (vCount == 0) data->pending0 = vertex;
|
||||
else if (vCount == 1) data->pending1 = vertex;
|
||||
else
|
||||
{
|
||||
/* In order to produce consistent winding, the vertex->triangle
|
||||
order for GL_TRIANGLE_STRIP is:
|
||||
0, 1, 2
|
||||
2, 1, 3
|
||||
2, 3, 4
|
||||
4, 3, 5
|
||||
4, 5, 6
|
||||
6, 5, 7
|
||||
6, 7, 8
|
||||
|
||||
Vertices 0 and 1 are special-cased above, and the first
|
||||
time we get here it's time for the first triangle, which
|
||||
is pending0, pending1, v. v (i.e., vertex 2) then goes into
|
||||
pending0.
|
||||
For the second triangle, the triangle is again pending0,
|
||||
pending1, v, and we then put v (i.e., vertex 3) into
|
||||
pending1.
|
||||
The third triangle follows the same pattern as the first,
|
||||
and the fourthe the same as the second.
|
||||
In other words, after storing each triangle, v goes into
|
||||
pending0 for even vertex indicies, and pending1 for odd
|
||||
vertex indices.
|
||||
*/
|
||||
data->OK = AppendVertex(data, data->pending0) &&
|
||||
AppendVertex(data, data->pending1) &&
|
||||
AppendVertex(data, vertex);
|
||||
OOLog(@"tesselate.vertex.strip", @"%u: (%@ %@) %@", vCount, NSStringFromPoint(data->pending0), NSStringFromPoint(data->pending1), NSStringFromPoint(vertex));
|
||||
if ((vCount % 2) == 0) data->pending0 = vertex;
|
||||
else data->pending1 = vertex;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifndef NDEBUG
|
||||
OOLog(@"polygonSprite.tesselate.error", @"Unexpected tesselator primitive mode %u.", data->mode);
|
||||
#endif
|
||||
data->OK = NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SolidEndCallback(void *polygonData)
|
||||
{
|
||||
TessPolygonData *data = polygonData;
|
||||
NSCParameterAssert(data != NULL);
|
||||
|
||||
data->mode = 0;
|
||||
data->vCount = 0;
|
||||
}
|
||||
|
||||
|
||||
static void ErrorCallback(GLenum error, void *polygonData)
|
||||
{
|
||||
TessPolygonData *data = polygonData;
|
||||
NSCParameterAssert(data != NULL);
|
||||
|
||||
NSString *name = @"";
|
||||
#ifndef NDEBUG
|
||||
name = [NSString stringWithFormat:@" \"%@\"", data->name];
|
||||
#endif
|
||||
|
||||
char *errStr = (char *)gluErrorString(error);
|
||||
|
||||
OOLog(@"polygonSprite.tesselate.error", @"Error %s (%u) while tesselating polygon%@.", errStr, error, name);
|
||||
data->OK = NO;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user