In Processing if I wanted to draw a globe and put a texture on it to create a 3D world it would be rather trivial. I'll add the code from a project I did where i placed tweets on a globe as well as had another texture map on top which was clouds. Is there some documentation someone can point me towards that would help me start trying to accomplish a similar output on the iPhone? I found some iOS snippets that helped me from the Programming 3D for the iPhone book. I'm trying to learn C4 and would like to approach the problem inside that framework. Thanks!
import processing.opengl.*;
PImage bg;
PImage texmap;
PImage clouds;
float cloudRotation = 0;
int sDetail = 35; // Default is 35
float rotationX = 0;
float rotationY = 0;
float velocityX = 0;
float velocityY = 0;
float globeRadius = 300;
float pushBack = 0;
float[] cx, cz, sphereX, sphereY, sphereZ;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5f;
int SINCOS_LENGTH = int( 360.0 / SINCOS_PRECISION );
void setup()
{
size( 640, 480, OPENGL );
texmap = loadImage( "world32k.jpg" );
clouds = loadImage( "clouds.png" );
initializeSphere( sDetail );
};
void draw()
{
background( 0 );
renderGlobe();
};
void renderGlobe()
{
pushMatrix();
translate( width / 2.0, height / 2.0, pushBack );
pushMatrix();
noFill();
//stroke( 255, 200 );
//strokeWeight( 2 );
smooth();
popMatrix();
lights();
pushMatrix();
rotateX( radians( 0 - rotationX ));
rotateY( radians( 270 - rotationY ));
fill( 200 );
textureMode( IMAGE );
texturedSphere( globeRadius, texmap, 255, false );
pushMatrix();
noStroke();
rotateY( radians( cloudRotation += 0.08 ));
texturedSphere( globeRadius + 20, clouds, 127, false );
popMatrix();
/////////////////////
// //
// Plot Points //
// //
/////////////////////
// For our purposes we need to spin the globe by 1/4
// in other words, 90 degrees.
rotateY( radians( 90 ));
noStroke();
fill( 255, 255, 0 );
// New York City
pushMatrix();
rotateY( radians( -73.967 )); // Longtitude 78.967 degress West (negative)
rotateX( radians( 40.783 )); // Latitude 40.783 degrees North (positive)
translate( 0, 0, globeRadius * 0.6 );
box( 4, 4, 100 );
popMatrix();
// Paris
pushMatrix();
rotateY( radians( 2.3 )); // Longtitude 2.3 degress East (positive)
rotateX( radians( 48.8 )); // Latitude 48.8 degrees North (positive)
translate( 0, 0, globeRadius * 0.6 );
box( 4, 4, 100 );
popMatrix();
// Dubai
pushMatrix();
rotateY( radians( 55.3 )); // Longitude 55.3 degrees East (positive)
rotateX( radians( 25.3 )); // Latitude 25.3 degrees North (positive)
translate( 0, 0, globeRadius * 0.6 );
box( 4, 4, 100 );
popMatrix();
// Sydney
pushMatrix();
rotateY( radians( 151 )); // Longtitude 151 degress East (positive)
rotateX( radians( -34 )); // Latitude 34 degrees South (negative)
translate( 0, 0, globeRadius * 0.6 );
box( 4, 4, 100 );
popMatrix();
// Seol
pushMatrix();
rotateY( radians( 127 )); // Longtitude 127 degress East (positive)
rotateX( radians( 37 )); // Latitude 37 degrees North (positive)
translate( 0, 0, globeRadius * 0.6 );
box( 4, 4, 100 );
popMatrix();
// Santiago
pushMatrix();
rotateY( radians( -70 )); // Longtitude 70 degress West (negative)
rotateX( radians( -33 )); // Latitude 33 degrees South (negative)
translate( 0, 0, globeRadius * 0.6 );
box( 4, 4, 100 );
popMatrix();
// Nairobi
pushMatrix();
rotateY( radians( 36 )); // Longtitude 36 degress East (positive)
rotateX( radians( -1 )); // Latitude 1 degrees South (negative)
translate( 0, 0, globeRadius * 0.6 );
box( 4, 4, 100 );
popMatrix();
popMatrix();
popMatrix();
rotationX += velocityX;
rotationY += velocityY;
velocityX *= 0.95;
velocityY *= 0.95;
// Implements mouse control
// interaction will be inverse when sphere is upside down
if( mousePressed )
{
velocityX += ( mouseY - pmouseY ) * 0.01;
velocityY -= ( mouseX - pmouseX ) * 0.01;
};
};
void initializeSphere( int res )
{
sinLUT = new float[SINCOS_LENGTH];
cosLUT = new float[SINCOS_LENGTH];
for( int i = 0; i < SINCOS_LENGTH; i ++ )
{
sinLUT[i] = (float) Math.sin( i * DEG_TO_RAD * SINCOS_PRECISION );
cosLUT[i] = (float) Math.cos( i * DEG_TO_RAD * SINCOS_PRECISION );
};
float delta = (float) SINCOS_LENGTH / res;
float[] cx = new float[ res ];
float[] cz = new float[ res ];
// Calc unit circle in XZ plane
for( int i = 0; i < res; i ++ )
{
cx[i] = -cosLUT[ (int) (i * delta) % SINCOS_LENGTH ];
cz[i] = sinLUT[ (int) (i * delta) % SINCOS_LENGTH ];
};
// Computing vertexlist vertexlist starts at south pole
int vertCount = res * (res - 1) + 2;
int currVert = 0;
// Re-initialize arrays to store vertices
sphereX = new float[ vertCount ];
sphereY = new float[ vertCount ];
sphereZ = new float[ vertCount ];
float angle_step = (SINCOS_LENGTH*0.5f)/res;
float angle = angle_step;
// Step along Y axis
for( int i = 1; i < res; i ++ )
{
float curradius = sinLUT[ (int) angle % SINCOS_LENGTH ];
float currY = -cosLUT[ (int) angle % SINCOS_LENGTH ];
for( int j = 0; j < res; j ++ )
{
sphereX[ currVert ] = cx[j] * curradius;
sphereY[ currVert ] = currY;
sphereZ[ currVert ++ ] = cz[j] * curradius;
};
angle += angle_step;
};
sDetail = res;
};
// Generic routine to draw textured sphere
void texturedSphere( float r, PImage t, int alpha, boolean showOutlines )
{
fill( 255, alpha );
int v1, v11, v2;
r = (r + 240) * 0.33;
beginShape( TRIANGLE_STRIP );
texture( t );
//tint(255,255,255,255);
if( showOutlines )
{
strokeWeight( 3 );
stroke( 255, 31 );
};
float iu = (float) (t.width - 1) / (sDetail);
float iv = (float) (t.height - 1) / (sDetail);
float u = 0, v = iv;
for( int i = 0; i < sDetail; i ++ )
{
vertex( 0, -r, 0, u, 0 );
vertex( sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v );
u += iu;
};
vertex( 0, -r, 0, u, 0 );
vertex( sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v );
endShape();
// Middle rings
int voff = 0;
for( int i = 2; i < sDetail; i ++ )
{
v1 = v11 = voff;
voff += sDetail;
v2 = voff;
u = 0;
beginShape( TRIANGLE_STRIP );
texture( t );
for( int j = 0; j < sDetail; j ++ )
{
vertex( sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v );
vertex( sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v + iv );
u += iu;
};
// Close each ring
v1 = v11;
v2 = voff;
vertex( sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v );
vertex( sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v + iv );
endShape();
v += iv;
}
u = 0;
// Add the northern cap
beginShape( TRIANGLE_STRIP );
texture( t );
for( int i = 0; i < sDetail; i ++ )
{
v2 = voff + i;
vertex( sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v );
vertex( 0, r, 0, u, v + iv );
u += iu;
};
vertex( 0, r, 0,u, v + iv );
vertex( sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v );
endShape();
};
FIRST: I created a github project for this answer: GLExample4.6.3 that you can download and use to follow along.
When C4 was first developed an OpenGL ES 1 object, i.e. C4GL, was included in the framework. The recent development of the API has been on animation, interactivity and media with a reliance on Core Animation as the primary underlying framework. The C4GL object hasn't been updated in a while and there have been quite a few developments with iOS / GL in the last year and a half. For instance, there is GLKit.
That said, it is possible to do what you want (but you'll have to get your hands dirty with some OPENGL to make it happen).
In order to show that you CAN have interactive OpenGL objects in C4 I have looked to a tutorial from Ray Wenderlich that shows you how to have an interactive (rotating) 3D object.
I didn't touch much of the code from the RW example (only copying the contents of
viewDidLoad
into the init method).To build a C4 app that will incorporate a rotating object I did the following:
viewDidLoad
inHelloGLKitViewController.m
to theinitWithNibName:bundle:
Next, I changed the
C4Workspace.m
look like the following code blockSo, to continue with your project / question... A good place to start for you is to look at the
HelloGLKitViewController.m
file to do the following: