【问题标题】:Drawing a sphere or other 3D shapes in C4?在 C4 中绘制球体或其他 3D 形状?
【发布时间】:2013-09-09 21:03:30
【问题描述】:

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

};

【问题讨论】:

    标签: objective-c ios6 c4


    【解决方案1】:

    首先:我为此答案创建了一个 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. HelloGLKitViewController.mviewDidLoad的内容复制到initWithNibName: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. 大概可以摆脱闪烁的红色!

    【讨论】:

    • 嘿,收到此错误:C4Gesture.h 中的“非整数类型 'UISwipeGestureRecognizerDirection' ... 是无效的底层类型”我使用的是 10.8,xcode 5.0,刚刚下载了最新的 c4 安装程序并运行它。
    • 有趣。我认为新的安装程序已经解决了这个问题。您可以像现在一样发布整个项目的副本吗?如果您提供整个文件夹的链接,我可以查看它并查看发生了什么。 Github repo 或 zip 会很棒。
    猜你喜欢
    • 2011-03-11
    • 1970-01-01
    • 2014-09-23
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多