views:

98

answers:

3

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{
 return *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.

+2  A: 

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.

whooops
Ah I didn't even see that Vertex/Vector mismatch, many thanks.
T. Markle
+2  A: 

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.

Sven
Ah I suspected something like this might be necessary but I hadn't seen any examples that matched what I was doing. Many thanks.
T. Markle
Just thought I'd follow up- I implemented this method and corrected my Vertex/Vector3D mistake and it's working like a charm. Thank you all for your help.
T. Markle
+1  A: 

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.

walkytalky
I had tried some combinations of using pointers vs values but every time I used values the complier would throw up on me. I'll integrate your info with memcpy and (hopefully) get it all worked out. Cheers!
T. Markle