1
0
mirror of https://github.com/thes3m/XNI synced 2024-12-26 13:26:06 +01:00

Basic sprite batch functionality.

git-svn-id: http://xni.googlecode.com/svn/XNI@26 ac433895-eea3-a490-d80a-17149a75e588
This commit is contained in:
Matej Jan 2010-09-23 21:13:28 +00:00
parent f8840a70a6
commit ef414aae80
16 changed files with 745 additions and 64 deletions

View File

@ -91,9 +91,19 @@
- (void) dealloc
{
[ambientColor release];
[diffuseColor release];
[emissiveColor release];
[specularColor release];
[texture release];
[ambientLightColor release];
[directionalLight0 release];
[directionalLight1 release];
[directionalLight2 release];
[fogColor release];
[world release];
[view release];
[projection release];
[super dealloc];
}

View File

@ -35,6 +35,7 @@
int referenceStencil;
SamplerStateCollection *samplerStates;
TextureCollection *textures;
Viewport *viewport;
NSMutableArray *vertices;
}
@ -51,6 +52,7 @@
@property (nonatomic) int referenceStencil;
@property (nonatomic, readonly) SamplerStateCollection *samplerStates;
@property (nonatomic, readonly) TextureCollection *textures;
@property (nonatomic, retain) Viewport *viewport;
+ (int) getNumberOfVerticesForPrimitiveType:(PrimitiveType)primitiveType primitiveCount:(int)primitiveCount;

View File

@ -49,6 +49,7 @@
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
// Do the initial reset.
viewport = [[Viewport alloc] init];
[self reset];
// Initialize defaults.
@ -106,6 +107,7 @@
@synthesize referenceStencil;
@synthesize samplerStates;
@synthesize textures;
@synthesize viewport;
+ (int) getNumberOfVerticesForPrimitiveType:(PrimitiveType)primitiveType primitiveCount:(int)primitiveCount {
switch (primitiveType) {
@ -135,6 +137,11 @@
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
glViewport(0, 0, backingWidth, backingHeight);
self.viewport.x = 0;
self.viewport.y = 0;
self.viewport.width = backingWidth;
self.viewport.height = backingHeight;
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
@ -280,6 +287,7 @@
[rasterizerState release];
[samplerStates release];
[textures release];
[viewport release];
[super dealloc];
}

View File

@ -3,12 +3,13 @@
@class GraphicsResource, Texture, Texture2D, Effect, EffectTechnique, EffectPass, BasicEffect, DirectionalLight;
#import "VertexStructs.h"
@class VertexElement, VertexPositionColor, VertexPositionTexture, VertexDeclaration;
@class VertexArray, VertexPositionColorArray, VertexPositionTextureArray;
@class VertexElement, VertexPositionColor, VertexPositionTexture, VertexPositionColorTexture, VertexDeclaration;
@class VertexArray, VertexPositionColorArray, VertexPositionTextureArray, VertexPositionColorTextureArray;
@class VertexBuffer, VertexBufferBinding, IndexBuffer;
@class BlendState, DepthStencilState, RasterizerState, SamplerState, SamplerStateCollection, TextureCollection;
@class Viewport;
@protocol IGraphicsDeviceService;
@class GraphicsDevice, ReachGraphicsDevice, HiDefGraphicsDevice;

View File

@ -12,11 +12,13 @@
#import "VertexElement.h"
#import "VertexPositionColor.h"
#import "VertexPositionTexture.h"
#import "VertexPositionColorTexture.h"
#import "VertexDeclaration.h"
#import "VertexArray.h"
#import "VertexPositionColorArray.h"
#import "VertexPositionTextureArray.h"
#import "VertexPositionColorTextureArray.h"
#import "VertexBuffer.h"
#import "VertexBufferBinding.h"
@ -29,7 +31,10 @@
#import "SamplerStateCollection.h"
#import "TextureCollection.h"
#import "Viewport.h"
#import "IGraphicsDeviceService.h"
#import "GraphicsDevice.h"
#import "ReachGraphicsDevice.h"
#import "HiDefGraphicsDevice.h"
#import "HiDefGraphicsDevice.h"
#import "SpriteBatch.h"

View File

@ -11,34 +11,60 @@
#import "GraphicsResource.h"
@interface SpriteBatch : GraphicsResource {
SpriteSortMode sortMode;
BlendState *blendState;
SamplerState *samplerState;
DepthStencilState *depthStencilState;
RasterizerState *rasterizerState;
Effect *effect;
Matrix *transformMatrix;
BasicEffect *basicEffect;
BOOL beginCalled;
NSMutableArray *sprites;
VertexPositionColorTextureArray *vertexArray;
}
- (void) begin;
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState;
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState;
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState
SamplerState:(SamplerState*)samplerState
DepthStencilState:(DepthStencilState*)depthStencilState
RasterizerState:(RasterizerState*)rasterizerState;
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState
SamplerState:(SamplerState*)theSamplerState
DepthStencilState:(DepthStencilState*)theDepthStencilState
RasterizerState:(RasterizerState*)theRasterizerState;
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState
SamplerState:(SamplerState*)samplerState
DepthStencilState:(DepthStencilState*)depthStencilState
RasterizerState:(RasterizerState*)rasterizerState
Effect:(Effect*)effect;
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState
SamplerState:(SamplerState*)theSamplerState
DepthStencilState:(DepthStencilState*)theDepthStencilState
RasterizerState:(RasterizerState*)theRasterizerState
Effect:(Effect*)theEffect;
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState
SamplerState:(SamplerState*)samplerState
DepthStencilState:(DepthStencilState*)depthStencilState
RasterizerState:(RasterizerState*)rasterizerState
Effect:(Effect*)effect
TransformMatrix:(Matrix*)transformMatrix;
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState
SamplerState:(SamplerState*)theSamplerState
DepthStencilState:(DepthStencilState*)theDepthStencilState
RasterizerState:(RasterizerState*)theRasterizerState
Effect:(Effect*)theEffect
TransformMatrix:(Matrix*)theTransformMatrix;
- (void) draw:(Texture2D*)texture toRectangle:(Rectangle*)destinationRectangle tintWithColor:(Color*)color;
- (void) draw:(Texture2D*)texture toRectangle:(Rectangle*)destinationRectangle fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color;
- (void) draw:(Texture2D*)texture toRectangle:(Rectangle*)destinationRectangle fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin effects:(SpriteEffects)effects layerDepth:(float)layerDepth;
- (void) draw:(Texture2D*)texture to:(Vector2*)position tintWithColor:(Color*)color;
- (void) draw:(Texture2D*)texture to:(Vector2*)position fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color;
- (void) draw:(Texture2D*)texture to:(Vector2*)position fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scaleUniform:(float)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth;
- (void) draw:(Texture2D*)texture to:(Vector2*)position fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scale:(Vector2*)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth;
- (void) end;
@end

View File

@ -8,49 +8,421 @@
#import "SpriteBatch.h"
#import "Retronator.Xni.Framework.h"
#import "Retronator.Xni.Framework.Graphics.h"
@interface Sprite : NSObject
{
@public
Texture2D *texture;
Vector2Struct position;
Vector2Struct width;
Vector2Struct height;
RectangleStruct source;
uint color;
float rotation;
Vector2Struct origin;
SpriteEffects effects;
float layerDepth;
}
@property (nonatomic, readonly) Texture2D *texture;
@property (nonatomic, readonly) float layerDepth;
@end
@implementation Sprite
@synthesize texture;
@synthesize layerDepth;
@end
Matrix *identity;
NSArray *textureSort;
NSArray *frontToBackSort;
NSArray *backToFrontSort;
static inline void SpriteSetSource(Sprite *sprite, Rectangle *source, Texture2D *texture) {
if (source) {
sprite->source.x = source.data->x / texture.width;
sprite->source.y = source.data->y / texture.height;
sprite->source.width = source.data->width / texture.width;
sprite->source.height = source.data->height / texture.height;
} else {
sprite->source.width = 1;
sprite->source.height = 1;
}
}
static inline void SpriteSetDestination(Sprite *sprite, Rectangle *destination) {
sprite->position.x = destination.x;
sprite->position.y = destination.y;
sprite->width.x = destination.width;
sprite->height.y = destination.height;
}
static inline void SpriteSetPositionFast(Sprite *sprite, Vector2 *position, Texture2D *texture) {
sprite->position.x = position.x;
sprite->position.y = position.y;
sprite->width.x = texture.width;
sprite->height.y = texture.height;
}
static inline void SpriteSetPosition(Sprite *sprite, Vector2 *position, float originX, float originY, float scaleX, float scaleY, float rotation, Texture2D *texture) {
float x = originX * scaleX;
float y = originY * scaleY;
float c = cos(rotation);
float s = sin(rotation);
sprite->position.x = position.x - x * c - y * s;
sprite->position.y = position.y - x * s + y * c;
sprite->width.x = texture.width * scaleX * c;
sprite->width.y = texture.width * scaleX * s;
sprite->height.x = -texture.height * scaleY * s;
sprite->height.y = texture.height * scaleY * c;
}
@interface SpriteBatch()
- (void) apply;
- (void) draw:(Sprite*)sprite;
- (void) draw;
- (void) drawFrom:(int)startIndex to:(int)endIndex;
@end
@implementation SpriteBatch
// Recyclable vertices
static VertexPositionColorTextureStruct vertices[4];
- (id) initWithGraphicsDevice:(GraphicsDevice *)theGraphicsDevice
{
self = [super initWithGraphicsDevice:theGraphicsDevice];
if (self != nil) {
basicEffect = [[BasicEffect alloc] initWithGraphicsDevice:theGraphicsDevice];
Matrix *projection = [Matrix createOrthographicOffCenterWithLeft:0
right:theGraphicsDevice.viewport.width
bottom:theGraphicsDevice.viewport.height
top:0
zNearPlane:0
zFarPlane:1];
Matrix *halfPixelOffset = [Matrix createTranslation:[Vector3 vectorWithX:-0.5f y:-0.5f z:0]];
basicEffect.projection = [Matrix multiply:halfPixelOffset by:projection];
basicEffect.textureEnabled = YES;
basicEffect.vertexColorEnabled = YES;
sprites = [[NSMutableArray alloc] init];
vertexArray = [[VertexPositionColorTextureArray alloc] initWithInitialCapacity:256];
}
return self;
}
+ (void) initialize {
identity = [[Matrix identity] retain];
NSSortDescriptor *textureSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"texture" ascending:YES] autorelease];
NSSortDescriptor *depthAscendingSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"layerDepth" ascending:YES] autorelease];
NSSortDescriptor *depthDescendingSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"layerDepth" ascending:NO] autorelease];
textureSort = [[NSArray arrayWithObject:textureSortDescriptor] retain];
// For better performance, depth sorting sorts by depth first and later also by texture.
frontToBackSort = [[NSArray arrayWithObjects:depthAscendingSortDescriptor, textureSortDescriptor, nil] retain];
backToFrontSort = [[NSArray arrayWithObjects:depthDescendingSortDescriptor, textureSortDescriptor, nil] retain];
}
- (void) begin {
[self beginWithSortMode:SpriteSortModeDeffered BlendState:nil SamplerState:nil DepthStencilState:nil RasterizerState:nil Effect:nil TransformMatrix:nil];
}
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState {
[self beginWithSortMode:sortMode BlendState:blendState SamplerState:nil DepthStencilState:nil RasterizerState:nil Effect:nil TransformMatrix:nil];
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState {
[self beginWithSortMode:theSortMode BlendState:theBlendState SamplerState:nil DepthStencilState:nil RasterizerState:nil Effect:nil TransformMatrix:nil];
}
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState
SamplerState:(SamplerState*)samplerState
DepthStencilState:(DepthStencilState*)depthStencilState
RasterizerState:(RasterizerState*)rasterizerState {
[self beginWithSortMode:sortMode BlendState:blendState SamplerState:samplerState DepthStencilState:depthStencilState RasterizerState:rasterizerState Effect:nil TransformMatrix:nil];
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState
SamplerState:(SamplerState*)theSamplerState
DepthStencilState:(DepthStencilState*)theDepthStencilState
RasterizerState:(RasterizerState*)theRasterizerState {
[self beginWithSortMode:theSortMode BlendState:theBlendState SamplerState:theSamplerState DepthStencilState:theDepthStencilState RasterizerState:theRasterizerState Effect:nil TransformMatrix:nil];
}
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState
SamplerState:(SamplerState*)samplerState
DepthStencilState:(DepthStencilState*)depthStencilState
RasterizerState:(RasterizerState*)rasterizerState
Effect:(Effect*)effect {
[self beginWithSortMode:sortMode BlendState:blendState SamplerState:samplerState DepthStencilState:depthStencilState RasterizerState:rasterizerState Effect:effect TransformMatrix:nil];
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState
SamplerState:(SamplerState*)theSamplerState
DepthStencilState:(DepthStencilState*)theDepthStencilState
RasterizerState:(RasterizerState*)theRasterizerState
Effect:(Effect*)theEffect {
[self beginWithSortMode:theSortMode BlendState:theBlendState SamplerState:theSamplerState DepthStencilState:theDepthStencilState RasterizerState:theRasterizerState Effect:theEffect TransformMatrix:nil];
}
- (void) beginWithSortMode:(SpriteSortMode)sortMode
BlendState:(BlendState*)blendState
SamplerState:(SamplerState*)samplerState
DepthStencilState:(DepthStencilState*)depthStencilState
RasterizerState:(RasterizerState*)rasterizerState
Effect:(Effect*)effect
TransformMatrix:(Matrix*)transformMatrix {
if (!blendState) blendState = [BlendState alphaBlend];
if (!samplerState) samplerState = [SamplerState linearClamp];
if (!depthStencilState) depthStencilState = [DepthStencilState none];
if (!rasterizerState) rasterizerState = [RasterizerState cullCounterClockwise];
- (void) beginWithSortMode:(SpriteSortMode)theSortMode
BlendState:(BlendState*)theBlendState
SamplerState:(SamplerState*)theSamplerState
DepthStencilState:(DepthStencilState*)theDepthStencilState
RasterizerState:(RasterizerState*)theRasterizerState
Effect:(Effect*)theEffect
TransformMatrix:(Matrix*)theTransformMatrix {
if (!theBlendState) theBlendState = [BlendState alphaBlend];
if (!theSamplerState) theSamplerState = [SamplerState linearClamp];
if (!theDepthStencilState) theDepthStencilState = [DepthStencilState none];
if (!theRasterizerState) theRasterizerState = [RasterizerState cullCounterClockwise];
if (!theEffect) theEffect = basicEffect;
if (!theTransformMatrix) theTransformMatrix = [Matrix identity];
sortMode = theSortMode;
blendState = theBlendState;
depthStencilState = theDepthStencilState;
rasterizerState = theRasterizerState;
samplerState = theSamplerState;
basicEffect.world = theTransformMatrix;
// Immediate mode applies the device state during begin.
if (sortMode == SpriteSortModeImmediate) {
[self apply];
}
beginCalled = YES;
}
- (void) draw:(Texture2D*)texture toRectangle:(Rectangle*)destinationRectangle tintWithColor:(Color*)color {
Sprite *sprite = [[[Sprite alloc] init] autorelease];
sprite->texture = texture;
SpriteSetDestination(sprite, destinationRectangle);
SpriteSetSource(sprite, nil, texture);
sprite->color = color.packedValue;
[self draw:sprite];
}
- (void) draw:(Texture2D*)texture toRectangle:(Rectangle*)destinationRectangle fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color {
Sprite *sprite = [[[Sprite alloc] init] autorelease];
sprite->texture = texture;
SpriteSetDestination(sprite, destinationRectangle);
SpriteSetSource(sprite, sourceRectangle, texture);
sprite->color = color.packedValue;
[self draw:sprite];
}
- (void) draw:(Texture2D*)texture toRectangle:(Rectangle*)destinationRectangle fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin effects:(SpriteEffects)effects layerDepth:(float)layerDepth {
Sprite *sprite = [[[Sprite alloc] init] autorelease];
sprite->texture = texture;
SpriteSetDestination(sprite, destinationRectangle);
SpriteSetSource(sprite, sourceRectangle, texture);
sprite->color = color.packedValue;
sprite->rotation = rotation;
sprite->origin = *origin.data;
sprite->effects = effects;
sprite->layerDepth = layerDepth;
[self draw:sprite];
}
- (void) draw:(Texture2D*)texture to:(Vector2*)position tintWithColor:(Color*)color {
Sprite *sprite = [[[Sprite alloc] init] autorelease];
sprite->texture = texture;
SpriteSetPositionFast(sprite, position, texture);
SpriteSetSource(sprite, nil, texture);
sprite->color = color.packedValue;
[self draw:sprite];
}
- (void) draw:(Texture2D*)texture to:(Vector2*)position fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color {
Sprite *sprite = [[[Sprite alloc] init] autorelease];
sprite->texture = texture;
SpriteSetPositionFast(sprite, position, texture);
SpriteSetSource(sprite, sourceRectangle, texture);
sprite->color = color.packedValue;
[self draw:sprite];
}
- (void) draw:(Texture2D*)texture to:(Vector2*)position fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scaleUniform:(float)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth {
Sprite *sprite = [[[Sprite alloc] init] autorelease];
sprite->texture = texture;
SpriteSetPosition(sprite, position, origin.x, origin.y, scale, scale, rotation, texture);
sprite->source = *sourceRectangle.data;
sprite->color = color.packedValue;
sprite->rotation = rotation;
sprite->origin = *origin.data;
sprite->effects = effects;
sprite->layerDepth = layerDepth;
[self draw:sprite];
}
- (void) draw:(Texture2D*)texture to:(Vector2*)position fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scale:(Vector2*)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth {
Sprite *sprite = [[[Sprite alloc] init] autorelease];
sprite->texture = texture;
SpriteSetPosition(sprite, position, origin.x, origin.y, scale.x, scale.y, rotation, texture);
SpriteSetSource(sprite, sourceRectangle, texture);
sprite->color = color.packedValue;
sprite->rotation = rotation;
sprite->origin = *origin.data;
sprite->effects = effects;
sprite->layerDepth = layerDepth;
[self draw:sprite];
}
- (void) draw:(Sprite *)sprite {
[sprites addObject:sprite];
if (sortMode == SpriteSortModeImmediate) {
[self draw];
}
}
- (void) end {
if (!beginCalled) {
[NSException raise:@"InvalidOperationException" format:@"End was called before begin."];
}
switch (sortMode) {
case SpriteSortModeImmediate:
// We've already done all the work.
return;
case SpriteSortModeTexture:
[sprites sortUsingDescriptors:textureSort];
break;
case SpriteSortModeBackToFront:
[sprites sortUsingDescriptors:backToFrontSort];
break;
case SpriteSortModeFrontToBack:
[sprites sortUsingDescriptors:frontToBackSort];
break;
}
// Apply the graphics device states.
[self apply];
// Render the whole array of sprites.
[self draw];
// Clean up.
[sprites removeAllObjects];
beginCalled = NO;
}
- (void) apply {
graphicsDevice.blendState = blendState;
graphicsDevice.depthStencilState = depthStencilState;
graphicsDevice.rasterizerState = rasterizerState;
[graphicsDevice.samplerStates insertObject:samplerState atIndex:0];
}
- (void) draw {
int count = [sprites count];
if (count == 0) {
// No sprites to draw.
return;
}
int startIndex = 0;
int endIndex = 0;
// Continue until all sprites are drawn.
while (startIndex < count) {
// Get the texture for the next batch.
Texture2D *currentTexture = ((Sprite*)[sprites objectAtIndex:startIndex]).texture;
// Try to expend the end to include all sprites with the same texture.
if (count > 1) {
while (endIndex + 1 < count && ((Sprite*)[sprites objectAtIndex:endIndex + 1]).texture == currentTexture) {
endIndex++;
}
}
// Draw sprites from start to end.
[self drawFrom:startIndex to:endIndex];
// Start a new batch.
startIndex = endIndex + 1;
endIndex = startIndex;
}
}
- (void) drawFrom:(int)startIndex to:(int)endIndex {
// Fill the vertex array
for (int i = startIndex; i <= endIndex; i++) {
Sprite *sprite = [sprites objectAtIndex:i];
vertices[0].position.x = sprite->position.x;
vertices[0].position.y = sprite->position.y;
vertices[0].position.z = sprite->layerDepth;
vertices[1].position.x = vertices[0].position.x + sprite->height.x;
vertices[1].position.y = vertices[0].position.y + sprite->height.y;
vertices[1].position.z = sprite->layerDepth;
vertices[2].position.x = vertices[0].position.x + sprite->width.x;
vertices[2].position.y = vertices[0].position.y + sprite->width.y;
vertices[2].position.z = sprite->layerDepth;
vertices[3].position.x = vertices[0].position.x + sprite->height.x + sprite->width.x;
vertices[3].position.y = vertices[0].position.y + sprite->height.y + sprite->width.y;
vertices[3].position.z = sprite->layerDepth;
if (sprite->effects & SpriteEffectsFlipHorizontally) {
vertices[0].texture.x = sprite->source.x + sprite->source.width;
vertices[1].texture.x = sprite->source.x + sprite->source.width;
vertices[2].texture.x = sprite->source.x;
vertices[3].texture.x = sprite->source.x;
} else {
vertices[0].texture.x = sprite->source.x;
vertices[1].texture.x = sprite->source.x;
vertices[2].texture.x = sprite->source.x + sprite->source.width;
vertices[3].texture.x = sprite->source.x + sprite->source.width;
}
if (sprite->effects & SpriteEffectsFlipVertically) {
vertices[0].texture.y = sprite->source.y + sprite->source.height;
vertices[1].texture.y = sprite->source.y + sprite->source.height;
vertices[2].texture.y = sprite->source.y;
vertices[3].texture.y = sprite->source.y;
} else {
vertices[0].texture.y = sprite->source.y;
vertices[1].texture.y = sprite->source.y + sprite->source.height;
vertices[2].texture.y = sprite->source.y;
vertices[3].texture.y = sprite->source.y + sprite->source.height;
}
vertices[0].color = sprite->color;
vertices[1].color = sprite->color;
vertices[2].color = sprite->color;
vertices[3].color = sprite->color;
[vertexArray addVertex:&vertices[0]];
[vertexArray addVertex:&vertices[1]];
[vertexArray addVertex:&vertices[2]];
[vertexArray addVertex:&vertices[2]];
[vertexArray addVertex:&vertices[1]];
[vertexArray addVertex:&vertices[3]];
}
// Apply the effect with the texture.
basicEffect.texture = ((Sprite*)[sprites objectAtIndex:startIndex]).texture;
[[basicEffect.currentTechnique.passes objectAtIndex:0] apply];
// Draw the vertex array.
int count = (endIndex - startIndex + 1) * 2;
[graphicsDevice drawUserPrimitivesOfType:PrimitiveTypeTriangleList vertices:vertexArray startingAt:0 count:count];
// Clean up.
[vertexArray clear];
}
- (void) dealloc
{
[sprites release];
[vertexArray release];
[super dealloc];
}
@end

View File

@ -0,0 +1,19 @@
//
// VertexPositionColorTexture.h
// XNI
//
// Created by Matej Jan on 23.9.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "VertexElement.h"
@interface VertexPositionColorTexture : VertexElement {
}
+ (VertexDeclaration*) vertexDeclaration;
@end

View File

@ -0,0 +1,39 @@
//
// VertexPositionColorTexture.m
// XNI
//
// Created by Matej Jan on 23.9.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import "VertexPositionColorTexture.h"
#import "Retronator.Xni.Framework.Graphics.h"
@implementation VertexPositionColorTexture
VertexDeclaration *vertexDeclaration;
+ (void) initialize {
NSArray *vertexElements = [NSArray arrayWithObjects:
[VertexElement vertexElementWithOffset:offsetof(VertexPositionColorTextureStruct, position)
format:VertexElementFormatVector3
usage:VertexElementUsagePosition
usageIndex:0],
[VertexElement vertexElementWithOffset:offsetof(VertexPositionColorTextureStruct, color)
format:VertexElementFormatColor
usage:VertexElementUsageColor
usageIndex:0],
[VertexElement vertexElementWithOffset:offsetof(VertexPositionColorTextureStruct, texture)
format:VertexElementFormatVector2
usage:VertexElementUsageTextureCoordinate
usageIndex:0], nil];
vertexDeclaration = [[VertexDeclaration alloc] initWithElements:vertexElements];
}
+ (VertexDeclaration *) vertexDeclaration {
return vertexDeclaration;
}
@end

View File

@ -0,0 +1,21 @@
//
// VertexPositionColorTextureArray.h
// XNI
//
// Created by Matej Jan on 23.9.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "VertexArray.h"
@interface VertexPositionColorTextureArray : VertexArray {
}
- (id) initWithInitialCapacity:(int)initialCapacity;
- (void) addVertex:(VertexPositionColorTextureStruct*)vertex;
@end

View File

@ -0,0 +1,29 @@
//
// VertexPositionColorTextureArray.m
// XNI
//
// Created by Matej Jan on 23.9.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import "VertexPositionColorTextureArray.h"
#import "Retronator.Xni.Framework.Graphics.h"
@implementation VertexPositionColorTextureArray
- (id) initWithInitialCapacity:(int)initialCapacity {
if (self = [super initWithItemSize:sizeof(VertexPositionColorTextureStruct) initialCapacity:initialCapacity]) {
}
return self;
}
- (VertexDeclaration *) vertexDeclaration {
return [VertexPositionColorTexture vertexDeclaration];
}
- (void) addVertex:(VertexPositionColorTextureStruct*)vertex {
[super addVertex:vertex];
}
@end

View File

@ -0,0 +1,31 @@
//
// Viewport.h
// XNI
//
// Created by Matej Jan on 23.9.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Retronator.Xni.Framework.classes.h"
@interface Viewport : NSObject {
int height;
float maxDepth;
float minDepth;
int width;
int x;
int y;
}
@property (nonatomic, readonly) float aspectRatio;
@property (nonatomic) int height;
@property (nonatomic) float maxDepth;
@property (nonatomic) float minDepth;
@property (nonatomic, readonly) Rectangle *titleSafeArea;
@property (nonatomic) int width;
@property (nonatomic) int x;
@property (nonatomic) int y;
@end

View File

@ -0,0 +1,32 @@
//
// Viewport.m
// XNI
//
// Created by Matej Jan on 23.9.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import "Viewport.h"
#import "Retronator.Xni.Framework.h"
@implementation Viewport
- (float) aspectRatio {
return (float)width/(float)height;
}
@synthesize height;
@synthesize maxDepth;
@synthesize minDepth;
- (Rectangle *) titleSafeArea {
int border = height * 0.05;
return [Rectangle rectangleWithX:x + border y:y + border width:width - 2 * border height:height - 2* border];
}
@synthesize width;
@synthesize x;
@synthesize y;
@end

View File

@ -26,8 +26,18 @@
+ (Matrix*) createFromAxis:(Vector3*)axis angle:(float)angle;
+ (Matrix*) createFromQuaternion:(Quaternion*)quaternion;
+ (Matrix*) createLookAtFrom:(Vector3*)position to:(Vector3*)target up:(Vector3*)up;
+ (Matrix*) createPerspectiveWithWidth:(float)width height:(float)height nearPlane:(float)nearPlane farPlane:(float)farPlane;
+ (Matrix*) createPerspectiveFieldOfView:(float)fieldOfView aspectRatio:(float)aspectRatio nearPlane:(float)nearPlane farPlane:(float)farPlane;
+ (Matrix*) createOrthographicWithWidth:(float)width height:(float)height
zNearPlane:(float)zNearPlane zFarPlane:(float)zFarPlane;
+ (Matrix*) createOrthographicOffCenterWithLeft:(float)left right:(float)right
bottom:(float)bottom top:(float)top
zNearPlane:(float)zNearPlane zFarPlane:(float)zFarPlane;
+ (Matrix*) createPerspectiveWithWidth:(float)width height:(float)height
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance;
+ (Matrix*) createPerspectiveFieldOfView:(float)fieldOfView aspectRatio:(float)aspectRatio
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance;
+ (Matrix*) createPerspectiveOffCenterWithLeft:(float)left right:(float)right
bottom:(float)bottom top:(float)top
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance;
+ (Matrix*) createWorldAtPosition:(Vector3*)position forward:(Vector3*)forward up:(Vector3*)up;
@property (nonatomic, readonly) MatrixStruct *data;

View File

@ -123,20 +123,72 @@
return matrix;
}
+ (Matrix*) createPerspectiveWithWidth:(float)width height:(float)height nearPlane:(float)nearPlane farPlane:(float)farPlane {
+ (Matrix*) createOrthographicWithWidth:(float)width height:(float)height
zNearPlane:(float)zNearPlane zFarPlane:(float)zFarPlane {
Matrix *matrix = [Matrix zero];
matrix.data->m11 = (2 * nearPlane) / width;
matrix.data->m22 = (2 * nearPlane) / height;
matrix.data->m33 = farPlane / (nearPlane - farPlane);
matrix.data->m34 = -1;
matrix.data->m43 = nearPlane * farPlane / (nearPlane - farPlane);
return matrix;
matrix.data->m11 = 2 / width;
matrix.data->m22 = 2 / height;
matrix.data->m33 = 1 / (zNearPlane - zFarPlane);
matrix.data->m43 = zNearPlane / (zNearPlane - zFarPlane);
matrix.data->m44 = 1;
return matrix;
}
+ (Matrix*) createPerspectiveFieldOfView:(float)fieldOfView aspectRatio:(float)aspectRatio nearPlane:(float)nearPlane farPlane:(float)farPlane{
float width = 2 * nearPlane * tanf(fieldOfView * 0.5f);
float height = width / aspectRatio;
return [Matrix createPerspectiveWithWidth:width height:height nearPlane:nearPlane farPlane:farPlane];
+ (Matrix*) createOrthographicOffCenterWithLeft:(float)left right:(float)right
bottom:(float)bottom top:(float)top
zNearPlane:(float)zNearPlane zFarPlane:(float)zFarPlane {
Matrix *matrix = [Matrix zero];
matrix.data->m11 = 2 / (right - left);
matrix.data->m22 = 2 / (top - bottom);
matrix.data->m33 = 1 / (zNearPlane - zFarPlane);
matrix.data->m41 = (left + right) / (left - right);
matrix.data->m42 = (top + bottom) / (bottom - top);
matrix.data->m43 = zNearPlane / (zNearPlane - zFarPlane);
matrix.data->m44 = 1;
return matrix;
}
+ (Matrix*) createPerspectiveWithWidth:(float)width height:(float)height
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance {
Matrix *matrix = [Matrix zero];
matrix.data->m11 = (2 * nearPlaneDistance) / width;
matrix.data->m22 = (2 * nearPlaneDistance) / height;
matrix.data->m33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
matrix.data->m34 = -1;
matrix.data->m43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
return matrix;
}
+ (Matrix*) createPerspectiveFieldOfView:(float)fieldOfView aspectRatio:(float)aspectRatio
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance {
float yScale = 1.0f / tanf(fieldOfView / 2.0f);
float xScale = yScale / aspectRatio;
Matrix *matrix = [Matrix zero];
matrix.data->m11 = xScale;
matrix.data->m22 = yScale;
matrix.data->m33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
matrix.data->m34 = -1;
matrix.data->m43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
return matrix;
}
+ (Matrix*) createPerspectiveOffCenterWithLeft:(float)left right:(float)right
bottom:(float)bottom top:(float)top
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance {
Matrix *matrix = [Matrix zero];
matrix.data->m11 = (2 * nearPlaneDistance) / (right - left);
matrix.data->m22 = (2 * nearPlaneDistance) / (top - bottom);
matrix.data->m31 = (2 * nearPlaneDistance) / (left + right) / (right - left);
matrix.data->m31 = (2 * nearPlaneDistance) / (top + bottom) / (top - bottom);
matrix.data->m33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
matrix.data->m34 = -1;
matrix.data->m43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
return matrix;
}
+ (Matrix*) createWorldAtPosition:(Vector3 *)position forward:(Vector3 *)forward up:(Vector3 *)up {

View File

@ -29,6 +29,12 @@
B56CC5C8123A928A00B72347 /* ContentTypeReaderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B56CC5C6123A928A00B72347 /* ContentTypeReaderManager.m */; };
B56CC5CB123A92BB00B72347 /* Texture2DContentTypeReader.h in Headers */ = {isa = PBXBuildFile; fileRef = B56CC5C9123A92BB00B72347 /* Texture2DContentTypeReader.h */; settings = {ATTRIBUTES = (Public, ); }; };
B56CC5CC123A92BB00B72347 /* Texture2DContentTypeReader.m in Sources */ = {isa = PBXBuildFile; fileRef = B56CC5CA123A92BB00B72347 /* Texture2DContentTypeReader.m */; };
B57E3665124BC23E00DDAA42 /* Viewport.h in Headers */ = {isa = PBXBuildFile; fileRef = B57E3663124BC23E00DDAA42 /* Viewport.h */; settings = {ATTRIBUTES = (Public, ); }; };
B57E3666124BC23E00DDAA42 /* Viewport.m in Sources */ = {isa = PBXBuildFile; fileRef = B57E3664124BC23E00DDAA42 /* Viewport.m */; };
B57E36BE124BE2DD00DDAA42 /* VertexPositionColorTexture.h in Headers */ = {isa = PBXBuildFile; fileRef = B57E36BC124BE2DD00DDAA42 /* VertexPositionColorTexture.h */; settings = {ATTRIBUTES = (Public, ); }; };
B57E36BF124BE2DD00DDAA42 /* VertexPositionColorTexture.m in Sources */ = {isa = PBXBuildFile; fileRef = B57E36BD124BE2DD00DDAA42 /* VertexPositionColorTexture.m */; };
B57E36CC124BE36E00DDAA42 /* VertexPositionColorTextureArray.h in Headers */ = {isa = PBXBuildFile; fileRef = B57E36CA124BE36E00DDAA42 /* VertexPositionColorTextureArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
B57E36CD124BE36E00DDAA42 /* VertexPositionColorTextureArray.m in Sources */ = {isa = PBXBuildFile; fileRef = B57E36CB124BE36E00DDAA42 /* VertexPositionColorTextureArray.m */; };
B59AD7F01236E07300F99511 /* ContentImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = B59AD7EE1236E07300F99511 /* ContentImporter.h */; settings = {ATTRIBUTES = (Public, ); }; };
B59AD7F11236E07300F99511 /* ContentImporter.m in Sources */ = {isa = PBXBuildFile; fileRef = B59AD7EF1236E07300F99511 /* ContentImporter.m */; };
B59AD80C1236E21900F99511 /* Retronator.Xni.Framework.Content.Pipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = B59AD80B1236E21900F99511 /* Retronator.Xni.Framework.Content.Pipeline.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -197,6 +203,12 @@
B56CC5C6123A928A00B72347 /* ContentTypeReaderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContentTypeReaderManager.m; sourceTree = "<group>"; };
B56CC5C9123A92BB00B72347 /* Texture2DContentTypeReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Texture2DContentTypeReader.h; sourceTree = "<group>"; };
B56CC5CA123A92BB00B72347 /* Texture2DContentTypeReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Texture2DContentTypeReader.m; sourceTree = "<group>"; };
B57E3663124BC23E00DDAA42 /* Viewport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Viewport.h; sourceTree = "<group>"; };
B57E3664124BC23E00DDAA42 /* Viewport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Viewport.m; sourceTree = "<group>"; };
B57E36BC124BE2DD00DDAA42 /* VertexPositionColorTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VertexPositionColorTexture.h; sourceTree = "<group>"; };
B57E36BD124BE2DD00DDAA42 /* VertexPositionColorTexture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VertexPositionColorTexture.m; sourceTree = "<group>"; };
B57E36CA124BE36E00DDAA42 /* VertexPositionColorTextureArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VertexPositionColorTextureArray.h; sourceTree = "<group>"; };
B57E36CB124BE36E00DDAA42 /* VertexPositionColorTextureArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VertexPositionColorTextureArray.m; sourceTree = "<group>"; };
B59AD7EE1236E07300F99511 /* ContentImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentImporter.h; sourceTree = "<group>"; };
B59AD7EF1236E07300F99511 /* ContentImporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContentImporter.m; sourceTree = "<group>"; };
B59AD80B1236E21900F99511 /* Retronator.Xni.Framework.Content.Pipeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Retronator.Xni.Framework.Content.Pipeline.h; sourceTree = "<group>"; };
@ -502,6 +514,8 @@
B5EA636E124917E2001245A4 /* VertexPositionColor.m */,
B5EA65511249482D001245A4 /* VertexPositionTexture.h */,
B5EA65521249482D001245A4 /* VertexPositionTexture.m */,
B57E36BC124BE2DD00DDAA42 /* VertexPositionColorTexture.h */,
B57E36BD124BE2DD00DDAA42 /* VertexPositionColorTexture.m */,
B5BBC2AC1248F0C40066F5ED /* VertexDeclaration.h */,
B5BBC2AD1248F0C40066F5ED /* VertexDeclaration.m */,
B5EA638D1249229D001245A4 /* VertexArray.h */,
@ -510,6 +524,8 @@
B5EA655F1249495C001245A4 /* VertexPositionColorArray.m */,
B5EA657612494AC3001245A4 /* VertexPositionTextureArray.h */,
B5EA657712494AC3001245A4 /* VertexPositionTextureArray.m */,
B57E36CA124BE36E00DDAA42 /* VertexPositionColorTextureArray.h */,
B57E36CB124BE36E00DDAA42 /* VertexPositionColorTextureArray.m */,
B5BBC2D01248F98D0066F5ED /* VertexBuffer.h */,
B5BBC2D11248F98D0066F5ED /* VertexBuffer.m */,
B5BBC2EA1248FC7A0066F5ED /* VertexBufferBinding.h */,
@ -528,6 +544,8 @@
B5BBC1DF1248D5640066F5ED /* SamplerStateCollection.m */,
B5BBC1EF1248D6090066F5ED /* TextureCollection.h */,
B5BBC1F01248D6090066F5ED /* TextureCollection.m */,
B57E3663124BC23E00DDAA42 /* Viewport.h */,
B57E3664124BC23E00DDAA42 /* Viewport.m */,
B5DDE82A11FF10EF000DB38B /* IGraphicsDeviceService.h */,
B5DDE85A11FF1326000DB38B /* GraphicsDevice.h */,
B5DDE85B11FF1326000DB38B /* GraphicsDevice.m */,
@ -736,6 +754,9 @@
B5EA65D7124952C9001245A4 /* EffectTechnique.h in Headers */,
B5EA660212495618001245A4 /* BasicEffect.h in Headers */,
B5EA660D124956CE001245A4 /* DirectionalLight.h in Headers */,
B57E3665124BC23E00DDAA42 /* Viewport.h in Headers */,
B57E36BE124BE2DD00DDAA42 /* VertexPositionColorTexture.h in Headers */,
B57E36CC124BE36E00DDAA42 /* VertexPositionColorTextureArray.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -852,6 +873,9 @@
B5EA65D8124952C9001245A4 /* EffectTechnique.m in Sources */,
B5EA660312495618001245A4 /* BasicEffect.m in Sources */,
B5EA660E124956CE001245A4 /* DirectionalLight.m in Sources */,
B57E3666124BC23E00DDAA42 /* Viewport.m in Sources */,
B57E36BF124BE2DD00DDAA42 /* VertexPositionColorTexture.m in Sources */,
B57E36CD124BE36E00DDAA42 /* VertexPositionColorTextureArray.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};