在C4中绘制球体或其他3D形状?

时间:2013-09-09 21:03:31

标签: objective-c ios6 c4

在处理中如果我想绘制一个地球并在其上放置一个纹理以创建一个3D世界,那将是相当微不足道的。我将添加来自我所做的项目的代码,我在地球上放置推文,并在顶部有另一个纹理贴图,即云。是否有人可以指出哪些文件可以帮助我开始尝试在iPhone上完成类似的输出?我找到了一些iOS片段,这些片段帮助我从iPhone的Programming 3D中获得了帮助。我正在尝试学习C4,并希望解决该框架内的问题。谢谢!

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();

};

1 个答案:

答案 0 :(得分:0)

FIRST:我为这个答案创建了一个github项目:GLExample4.6.3,您可以下载并使用它来跟进。

首次开发C4时,框架中包含OpenGL ES 1对象,即C4GL。 API的最新发展一直是动画,交互和媒体,依赖于Core Animation作为主要的底层框架。 C4GL对象暂时没有更新,过去一年半的iOS / GL已经有了不少发展。例如,有GLKit。

也就是说,有可能做你想做的事(但是你必须用一些OPENGL弄脏你的手才能实现它)。

为了表明您可以在C4中拥有交互式OpenGL对象,我已经查看了Ray Wenderlich的教程,该教程向您展示了如何使用交互式(旋转)3D对象。

我没有触及RW示例中的大部分代码(仅将viewDidLoad的内容复制到init方法中)。

要构建一个包含旋转对象的C4应用程序,我执行了以下操作:

  1. 从RW
  2. 下载示例代码
  3. 创建一个新的C4应用程序(我在Xcode 4.6.3中这样做)
  4. 将HelloGLKitViewController文件(.h + .m)复制到C4应用程序
  5. 将tile_floor.png复制到C4应用程序
  6. viewDidLoadHelloGLKitViewController.m的内容复制到initWithNibName:bundle:
  7. 的Build Phases选项卡中将GLKit框架添加到C4 app项目

    接下来,我将C4Workspace.m更改为以下代码块

    #import "C4WorkSpace.h"
    #import <GLKit/GLKit.h>
    #import "HelloGLKitViewController.h"
    
    @interface C4WorkSpace ()
    @property (readwrite, strong) GLKView *glView;
    @property (readwrite, strong) HelloGLKitViewController *glViewController;
    @end
    
    @implementation C4WorkSpace
    
    -(void)setup {
        _glViewController = [[HelloGLKitViewController alloc] initWithNibName:nil bundle:nil];
        _glViewController.view.frame = CGRectMake(10,10,self.canvas.width-20,self.canvas.height-20);
        [self.canvas addSubview:_glViewController.view];
    }
    

    所以,继续你的项目/问题......一个好的开始就是查看HelloGLKitViewController.m文件来执行以下操作:

    1. 将立方体更改为球体(我不是GL wiz,但我猜测你必须更改文件顶部的顶点)。
    2. 将纹理重新映射到新球体
    3. 可能摆脱闪烁的红色!