I have an array of GLuint with fixed size:
GLuint textures[10];
Now I need to set a size of array dynamically. I wrote something like this:
*.h:
GLuint *textures;
*.m:
textures = malloc(N * sizeof(GLuint));
where N - needed size.
Then it used like this:
glGenTextures(N, &textures[0]);
// load texture from image
-(GLuint)getTexture:(int)index{
return textures[index];
}
I used the answer from here, but program fell in runtime. How to fix this?
Program is written on Objective-C and uses OpenGL ES.
I figured out this issue.
This code is valid but seems like not working. This problem is described here, but it's not so clear.
The solution that works for me is to create separate class with GLuint property:
#interface Texture : NSObject
GLuint texture;
#end
#property (nonatomic, readwrite) GLuint texture;
Then we can create NSMutableArray of Textures:
NSMutableArray *textures;
In *.m file we should fill our array:
for(int i=0;i<N;i++){
Texture *t = [[Texture alloc] init];
t.texture = i;
GLuint l = t.texture;
[textures addObject:t];
glGenTextures(1, &l);
}
If you use other array(s) with textures you have to shift GLuint indexes, e.g.:
t.texture = i+M;
where M - size of earlier used array of GLuint's.
Then getTexture will be rewritten as following:
-(GLuint)getTexture:(int)index{
return textures[index].texture;
}
I am not excited with this approach but it's a single one I make work.
If you set the value of N to 10, then the behavior of the two methods will be identical. You should therefore look for the reason for the failure in different places.
void glGenTextures( GLsizei n,
GLuint * textures);
accepts an array of unsigned ints, and it looks like you are passing a pointer to the first element in the array, which I think is not what you want to do or what the function accepts
maybe just try
glGenTextures(N, textures);
Related
I'll preface this question by saying that I am a total noob when it comes to Objective-C. So please, be patient with my question. :)
So here is my issue. I am basically allowing the user to 'rub out' an image by using alpha blending and such, and then converting the created texture to a CCSprite. I am then able to store the CCSprite in a function within my singleton class. Like so:
erasedTextureSprite = [CCSprite spriteWithTexture:darknessLayer.sprite.texture];
[[MySingleton sharedMySingleton] setRevealTexture:erasedTextureSprite];
Here is the setRevealTexture & getRevealTexture function as well as the revealTexture variable initialisation in my MySingleton.h file:
#interface MySingleton : NSObject
{
CCSprite *revealTexture;
}
...
-(void) setRevealTexture: (CCSprite *) texture;
-(CCSprite *) getRevealTexture;
And here are both functions in my MySingleton.m file:
-(void) setRevealTexture: (CCSprite *) texture
{
NSLog(#"set reveal texture.");
revealTexture = texture;
NSLog(#"%f", [revealTexture boundingBox].size.width);
}
-(CCSprite *) getRevealTexture
{
NSLog(#"got reveal texture.");
NSLog(#"%f", revealTexture.contentSize.width);
return revealTexture;
}
If I set the reveal texture, and then get it right away, it seems to return the sprite correctly. However, if I set the texture and then transition to another scene, it seems to lose it's value, and throws me an error when I try and call the getRevealTexture function.
Question: Why is my function not retaining it's value when I transition between scenes?
If any more clarification is needed please let me know!
Practically there is no point in using your own setter and getter if your not doing anything fancy.
What you are doing is using an iVar which should have been a strong property.
you could achieve the same by doing:
#property (nonatomic, strong) CCSprite *revealTexture;
in your header file.
You would then get the following 2 functions by default:
[[MySingleton sharedMySingleton] revealTexture];
[[MySingleton sharedMySingleton] setRevealTexture:texture];
My next point of failure that I would presume if this doesn't work is that your singleton function is not working properly and your actually getting a new instance each time.
You can easily find this out by doing in the debugger:
po [MySingleton sharedMySingleton]
And seeing the instance that is returned each time.
example for a basic singleton code:
static MySingleton *__sharedMySingleton = nil;
+ (id)sharedMySingleton {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__sharedMySingleton = [MySingleton new]; // or a specific alloc init function
});
return __sharedMySingleton;
}
Due to the request - here is a short image to explain how to enter debugger commands in xcode 5:
I know I can concatenate a variable name using stringwithformat, but is it possible to concatenate an object name? I'm not having any luck working around this one.
image+1.hidden = YES; for example.
If I wanted to loop through that, say 10 times, how would I create the 'image+1' part?
Thanks for any help.
I don't think that it is possible to concatenate object names in objective c, but you could create an array of images, and then reference each image like
image[0].hidden = YES;
That would fit the for loop. You could also add the images (I assume that they are UIImages) to an NSArray, then loop through like so:
NSArray* arrayOfImages;
for(UIImage* image in arrayOfImages)
{
image.hidden = YES;
}
Add the objects to an NSArray or NSMutableArray. Then loop through the array to set each object's properties.
For the purposes of discussion mainly, you can use key-value coding to set a property by its name. So, supposing you had instance, an instance of a class that provides the properties image1, image2 and image3 then you could perform:
for(int x = 1; x < 4; x++)
{
// produce the name of the property as an NSString
NSString *propertyName = [NSString stringWithFormat:#"image%d", x];
// use key-value coding to set the property
[instance setValue:someValue forKey:propertyName];
}
For the full list of accessor methods that compliant classes export, see the NSKeyValueCoding Protocol Reference. NSObject implements NSKeyValueCoding, and all properties declared as #property and implemented as #synthesize are compliant, as are any other properties with suitable accessors.
As already noted in the other answers, when what you want is an ordered list of objects so that you can do something with each in turn, either a C-style array or an NSArray is the correct way to proceed, with an NSArray being preferred for style reasons.
NSArray *array = [[NSArray alloc] initWithObjects:image1, image2, image3, image4, image5, image6, image7, image8, image9, image10, nil]; // or use NSMutableArray
for (int x = 0; x < 10; x++) {
((UIImage*)[array objectAtIndex:x]).hidden = YES;
}
I am currently doing image modification. I used a class of my own named "Image".
It looks like this:
#interface Image : NSObject {
#public
int height;
int width;
float* data;
}
So in data I have floats, in rgba format which mean they go four by four. I can't change my Image class.
I need to create a UIImage from my Image. I'm trying something like that:
+(UIImage *)getUIImageFromImage:(Image *)_img {
NSData * imageData = (NSData *) _img->data;
return [[UIImage alloc] initWithData:imageData];
}
Am I doing something wrong ? Is my cast to (NSData *) okay?
No it ain't. NSData is an Objective-C object. float * is a raw pointer to one or more float values.
If you tell us where this data comes from and what format it's in, we may be able to suggest a way to convert it to either an NSData object or to a CGImage Quartz value, which can then be wrapped in a UIImage and used with UIKit classes.
I am using cocos2d for the iphone
I want to create a class for Enemies
see my code
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface Enemies : CCSprite {
float imageHeight;
}
#property float imageHeight;
+(id) enemies;
#end
#implementation Enemies
#synthesize imageHeight;
+(id) enemies{
return [[[self alloc] initWithFile:#"enemy.png"] autorelease];
}
#end
I want the to set the imageHeight
float imageHeight = [enemy texture].contentSize.height;
so whenever I create an instance of the class Enemies I it should have imageHeight set properly?
Thanks
note: I am trying to improve this code
ahmed, keep the enemies method the same, and add this to your class:
-(id) init {
if (self = [super init]) {
float textureHeight = [enemy texture].contentSize.height;
[self setImageHeight:textureHeight];
}
return self;
}
This will set imageHeight for all new instances of the Enemies class.
Override initWithFile in Enemies class.
Then Inside it call, [super initWithFile passing the same Filename string]
After which you can set the imageHeight variable in the next line as the texture would have been loaded and height will be accessible.
Cocos2d automatically sets the height of some things based on the image itself. Look for the sprite's setHeight property, it should be easy to find in the docs.
However, your question looks like it could use rewording. Your "Enemy" should be data, not related to any display (sprites) whatsoever, unless you're going to make a really small app.
Check out Beginning XNA books for nice examples of how to abstract superclass enemy and players, if you can use C# and translate between iOS. They will work very much the same. (I wish I knew a good game programming book for iPhone, but all of the ones I open have flaws or bad design that only experienced programmers can get past.
Anywho, if you mix data and images, it usually means to redesign your code
I want to keep a mutable collection of CGImageRefs. Do I need to wrap them in NSValue, and if so how do I wrap and unwrap them properly? Can I get away with using a C array? If so how do I construct it and how do I add elements to it later? Is it significantly more costly to use UIImages instead of CGImageRefs as the elements of the collection?
You can directly add CGImage to NSMutableArray. You will need to cast to (id) to avoid compiler warnings.
CFType is bridged to NSObject. You can send any message NSObject responds to to any CFType. In particular, -retain and -release work as normal.
2011: just in case someone's still looking
You can wrap CGImageRef in NSValues by using
+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type
hence:
CGImageRef cgImage = [self cgImageMethod];
NSValue *cgImageValue = [NSValue valueWithBytes:&cgImage objCType:#encode(CGImageRef)];
[array addObject:cgImageValue];
to retrieve:
CGImageRef retrievedCGImageRef;
[[array objectAtIndex:0] getValue:&retrievedCGImageRef ];
hope this helps somebody
Getting the CGImageRef out of an UIImage via image.CGImage can be costly. From the documentation:
If the image data has been purged because of memory constraints, invoking this method forces that data to be loaded back into memory. Reloading the image data may incur a performance penalty.
If you feel comfortable with mixing C++ and Objective-C, you can use a std::vector for storing the CGImageRef. Rename your source file from .m to .mm and try this:
#include <vector>
...
CGImageRef i;
...
std::vector<CGImageRef> images;
images.push_back(i);
If you want to keep the vector as a member of a Objective-C class, you should allocate it on the heap, not the stack:
Header file:
#include <vector>
using std;
#interface YourInterface : ...
{
vector<CGImageRef> *images;
}
and in the implementation file:
images = new std::vector<CGImageRef>();
images->push_back(i);
...
//When you're done
delete images;
images = NULL;