1

在处理中,如果我想绘制一个地球并在其上放置一个纹理以创建一个 3D 世界,那将是相当微不足道的。我将从我所做的一个项目中添加代码,我在地球上放置了推文,并且在顶部有另一个纹理贴图,它是云。是否有人可以指出一些文档可以帮助我开始尝试在 iPhone 上完成类似的输出?我从 Programming 3D for the iPhone 一书中找到了一些对我有帮助的 iOS 片段。我正在尝试学习 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();

};
4

1 回答 1

0

首先:我为此答案创建了一个 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. 创建一个新的 C4 应用程序(我是在 Xcode 4.6.3 中完成的)
  3. 将 HelloGLKitViewController 文件 (.h + .m) 复制到 C4 应用程序中
  4. 将 tile_floor.png 复制到 C4 应用程序中
  5. viewDidLoad将in的内容复制HelloGLKitViewController.minitWithNibName:bundle:
  6. 从 Build Phases 选项卡将 GLKit 框架添加到 C4 应用程序项目

接下来,我改变了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 向导,但我猜您必须更改文件顶部的顶点)。
  2. 将纹理重新映射到新球体
  3. 大概摆脱了闪烁的红色!
于 2013-09-10T18:03:11.010 回答