Objective-C arrays and class variables
I am porting an Android app I made to iPhone and running into problems with the syntax (I think)
I'm basing the project off of the example from http://iphonedevelopment.blogspot.com/2009/04/opengl-es-from-ground-up-part-2-look-at.html
I would like to pull out the geometry from the rendering process to keep the code modular but I can't seem to get it to work. I've created a class called Icosahedron (comments are my understanding of what's going on) Icosahedron.h
#import <Foundation/Foundation.h>
#import "OpenGLCommon.h"
@interface Icosahedron : NSObject {
Vertex3D *vertices[12]; //allocate a group of 12 Vertex3D pointers
Vertex3D *normals[12]; // ditto
GLubyte *faces[60]; // ditto but with 60 face values
}
// Declare methods
-(Vertex3D *) vertices;
-(void) setVertices:(Vector3D *)setVerts;
-(Vertex3D *) normals;
-(void) setNormals:(Vector3D *)setNorms;
-(GLubyte *) faces;
-(void) setFaces:(GLubyte *)setFaces;
@end
Icosahedron.m
#import "Icosahedron.h"
@implementation Icosahedron
// Returns the pointer to the vertices instance variable
-(Vector3D *) vertices{
return *vertices;
}
-(void) setVertices:(Vector3D *)setVerts
{
//vertices=setVerts[0];
}
-(Vector3D *) normals{
return *normals;
}
-(void) setNormals:(Vector3D *)setNorms
{
//normals=setNorms;
}
-(GLubyte *) faces{
ret开发者_StackOverflowurn *faces;
}
-(void) setFaces:(GLubyte *)setFaces
{
//faces=setFaces;
}
/**/
-(id)init
{
// super method
self=[super init];
// create 12 Vector3D objects and populate them...
Vector3D tempVert[12]={
{0, -0.525731, 0.850651}, // vertices[0]
{0.850651, 0, 0.525731}, // vertices[1]
{0.850651, 0, -0.525731}, // vertices[2]
{-0.850651, 0, -0.525731}, // vertices[3]
{-0.850651, 0, 0.525731}, // vertices[4]
{-0.525731, 0.850651, 0}, // vertices[5]
{0.525731, 0.850651, 0}, // vertices[6]
{0.525731, -0.850651, 0}, // vertices[7]
{-0.525731, -0.850651, 0}, // vertices[8]
{0, -0.525731, -0.850651}, // vertices[9]
{0, 0.525731, -0.850651}, // vertices[10]
{0, 0.525731, 0.850651} // vertices[11]
};
// same...
Vector3D tempNorm[12]={
{0.000000, -0.417775, 0.675974},
{0.675973, 0.000000, 0.417775},
{0.675973, -0.000000, -0.417775},
{-0.675973, 0.000000, -0.417775},
{-0.675973, -0.000000, 0.417775},
{-0.417775, 0.675974, 0.000000},
{0.417775, 0.675973, -0.000000},
{0.417775, -0.675974, 0.000000},
{-0.417775, -0.675974, 0.000000},
{0.000000, -0.417775, -0.675973},
{0.000000, 0.417775, -0.675974},
{0.000000, 0.417775, 0.675973},
};
// face values
GLubyte tempFaces[60]={
1, 2, 6,
1, 7, 2,
3, 4, 5,
4, 3, 8,
6, 5, 11,
5, 6, 10,
9, 10, 2,
10, 9, 3,
7, 8, 9,
8, 7, 0,
11, 0, 1,
0, 11, 4,
6, 2, 10,
1, 6, 11,
3, 5, 10,
5, 4, 11,
2, 7, 9,
7, 1, 0,
3, 9, 8,
4, 8, 0,
};
// set the instance pointers to the temp values
*vertices=tempVert;
*normals=tempNorm;
*faces=tempFaces;
at this point the values are NOT properly populated, only the first value is correct.
return self;
}
@end
All I want to do is to be able to call something like
...
ico=[[Icosahedron alloc] init];
glVertexPointer(3, GL_FLOAT, 0, [ico vertices]);
...
in the rendering section but it the farthest I've been able to get is setting the first value of the Vertex3Ds inside the Icosahedron class and I get 'out of scope' in the debugger for any of the Icosahedron's values in the rendering class.
I suspect that this is just me learning Objective-C's quirks but I've tried many different approaches for a few days and nothing seems to get me anywhere.
Please help me Overflow-Wan, you're my only hope.
You’re getting your pointers and arrays mixed up. You’d want something like this:
Vertex3D vertices[12];
- (void) setVertices: (Vertex3D *)newVertices;
{
memcpy( vertices, newVertices, 12 * sizeof( Vertex3D ) );
}
- (Vertex3D *) vertices;
{
return vertices;
}
To copy arrays in C you have to use memcpy (or a hand-written loop), you cannot do this with the assignment operator.
Firstly, you seem to be using "Vertex3D" and "Vector3D" interchangeably. I don't know if that's actually a problem...
I think the arrays should be declared as arrays of values, not arrays of pointers. So...
Vertex3D vertices[12]; //allocate a group of 12 Vertex3D pointers
Vertex3D normals[12]; // ditto
GLubyte faces[60]; // ditto but with 60 face values
That way you have room for all the values, not just pointers to other vectors (which you haven't allocated).
As an aside, the typical init sequence is:
-(id)init
{
if (self = [super init])
{
//do initialization stuff
}
return self;
}
It handles errors more gracefully.
Your declarations of vertices
, normals
and faces
are to arrays of pointers to the entities in question. Whereas it seems like what you really want is to have arrays of the structs/values themselves. So your interface should say:
Vertex3D vertices[12];
Vertex3D normals[12];
GLubyte faces[60];
Your object will then own a chunk of memory containing 12 vertices, 12 normals and 60 faces (um, whatever those are -- GLubyte
values, anyway).
Pointers and arrays are sort of interchangeable in C/Objective-C. So vertices
and normals
can also be thought of as Vertex3D*
values, and faces
as a GLubyte*
, and they can be passed as such to functions that want those types.
To make it clear what's what, it would be better to have the initial values as single static const
arrays at the top level of your implementation file, and then copy those values into the object-owned arrays at initialisation time. You can do this several ways, but the simplest is probably to use memcpy
as in Sven's answer.
精彩评论