1

次の問題があります: Android の OpenGL ES で太陽系を作成しようとしています。私はすでにいくつかの球体を持っています。ここで、中心にある最大の球の周りを軌道で球を回転させたいと思います (惑星が太陽の周りを回転するように)。それ、どうやったら出来るの?それ自体の周りの球の回転は機能しますが、別の球の周りを回転させる方法がわかりません。

また、色にも問題があります。すべての「惑星」が灰色であるため、コードのどこかに問題があるはずです。太陽を赤くしようとしたのですが、なぜか灰色に固執してしまいます。gl.glColor4f を使用しましたが、動作するはずですが、動作しません。

助けてください。これは非常に緊急です。1 月 28 日の月曜日までに実行する必要があるためです。これは私が研究のために行っているプログラムであり、これらの問題を解決する方法が本当にわかりません。助けてください。ありがとうございました。

これが私のコードです:

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;

import my.pack.graphics.primitives.Sphere;

import android.app.Activity;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.widget.Toast;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

public class GLES06 extends Activity {
    private GLSurfaceView touchableGLSurfaceView;

    private final int MENU_RESET = 1, MENU_PAN = 2, MENU_ZOOM = 3;
    private final int GROUP_DEFAULT = 0, GROUP_PAN = 1, GROUP_ZOOM = 2;
    private boolean PAN = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    touchableGLSurfaceView = new TouchableGLSurfaceView(this);
    setContentView(touchableGLSurfaceView);
    touchableGLSurfaceView.setFocusableInTouchMode(true);
    touchableGLSurfaceView.requestFocus();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(GROUP_DEFAULT, MENU_RESET, 0, "Reset");
    menu.add(GROUP_PAN, MENU_PAN, 0, "Pan");
    menu.add(GROUP_ZOOM, MENU_ZOOM, 0, "Zoom");
    return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
    if (PAN) {
        menu.setGroupVisible(GROUP_PAN, false);
        menu.setGroupVisible(GROUP_ZOOM, true);
    } else {
        menu.setGroupVisible(GROUP_PAN, true);
        menu.setGroupVisible(GROUP_ZOOM, false);
    }
    return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case MENU_RESET:
            TouchableGLSurfaceView.resetViewing();
            Toast.makeText(this, "trackball reset",               
                            Toast.LENGTH_SHORT).show();
            touchableGLSurfaceView.requestRender();
            return true;
        case MENU_PAN:
            Toast.makeText(this, "panning activated", 
                            Toast.LENGTH_SHORT).show();
            PAN = true;
            TouchableGLSurfaceView.guiZoom = false;
            return true;
        case MENU_ZOOM:
            Toast.makeText(this, "zooming activated", 
                            Toast.LENGTH_SHORT).show();
            PAN = false;
            TouchableGLSurfaceView.guiZoom = true;
            return true;
    }
    return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() {
    super.onResume();
    touchableGLSurfaceView.onResume();
    }

    @Override
    protected void onPause() {
    super.onPause();
    touchableGLSurfaceView.onPause();
    }
 }

 // touchable GLSurfaceView with
 // an implementation of a virtual trackball rotation control
class TouchableGLSurfaceView extends GLSurfaceView {
    private OurRenderer ourRenderer;

    static public boolean guiZoom = true;
    // possible touch states
    final static int NONE = 0;
    final static int ROTATE = 1;
    final static int ZOOM = 2;
    final static int PAN = 3;
    int touchState = NONE;

    final static float MIN_DIST = 50;
    static int oldDistance = 0;
    static int centerX = 0, centerY = 0;
    static int oldCenterX = 0, oldCenterY = 0;

    static float EYE_DISTANCE, EYE_DISTANCE_INC;
    static float PAN_X, PAN_Y, PAN_INC;
    static float CURRENT_QUATERNION[], LAST_QUATERNION[];
    static float TRANSFORM_MATRIX[];

    static int OLD_MOUSE_X, OLD_MOUSE_Y, MOUSE_BUTTON_PRESSED;

    static int WINDOW_W = 600;
    static int WINDOW_H = 800;

    static float zNear = 1.0f, zFar = 1000.0f;

    static {
    CURRENT_QUATERNION = new float[4];
    LAST_QUATERNION = new float[4];
    TRANSFORM_MATRIX = new float[16];
    }

    public TouchableGLSurfaceView(Context context) {
    super(context);
    ourRenderer = new OurRenderer();
    setRenderer(ourRenderer);

    ourRenderer.autoRotate=true;
    setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    float p1x, p1y, p2x, p2y;
    // normalize mouse positions
    p1x = (2.0f * OLD_MOUSE_X - WINDOW_W) / WINDOW_W;
    p1y = (WINDOW_H - 2.0f * OLD_MOUSE_Y) / WINDOW_H;
    p2x = (2.0f * x - WINDOW_W) / WINDOW_W;
    p2y = (WINDOW_H - 2.0f * y) / WINDOW_H;

    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            touchState = ROTATE;
            OLD_MOUSE_X = (int) x;
            OLD_MOUSE_Y = (int) y;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            // secondary touch event starts: remember distance
            oldDistance = (int) calcDistance(event);
            // and midpoint
            calcMidpoint(event);
            oldCenterX = centerX;
            oldCenterY = centerY;
            if (oldDistance > MIN_DIST) {
                if (guiZoom) {
                    touchState = ZOOM;
                } else {
                    touchState = PAN;
                }
            }
            break;
        case MotionEvent.ACTION_MOVE:  
            if (touchState == ROTATE) {
                // single finger rotate
                Trackball.trackball(LAST_QUATERNION, p1x, p1y, 
                                                                         p2x, p2y);
                OLD_MOUSE_X = (int) x;
                OLD_MOUSE_Y = (int) y;
                Trackball.add_quats(LAST_QUATERNION, 
                                              CURRENT_QUATERNION, CURRENT_QUATERNION);
                requestRender();
            } else if (touchState == ZOOM) {
                // double-finger zoom, zoom depends on changing 
                                       distance
                int dist = (int) calcDistance(event);
                if (dist > MIN_DIST) {
                    if (dist > oldDistance)
                    EYE_DISTANCE -= EYE_DISTANCE_INC;
                    else if (dist < oldDistance)
                    EYE_DISTANCE += EYE_DISTANCE_INC;
                    oldDistance = dist;
                    requestRender();
                }
            } else if (touchState == PAN) {
                int dist = (int) calcDistance(event);
                calcMidpoint(event);
                if (dist > MIN_DIST) {
                    if (centerX > oldCenterX)
                    PAN_X -= PAN_INC;
                    if (centerX < oldCenterX)
                    PAN_X += PAN_INC;
                    if (centerY > oldCenterY)
                    PAN_Y += PAN_INC;
                    if (centerY < oldCenterY)
                    PAN_Y -= PAN_INC;
                    oldCenterX = centerX;
                    oldCenterY = centerY;
                    requestRender();
                }
            }
            break;
        case MotionEvent.ACTION_UP:
            touchState = NONE;
            break;
        case MotionEvent.ACTION_POINTER_UP:
            touchState = ROTATE;
            // update touch down location for drag event to holding finger
            switch (event.getActionIndex()) {
                case 0:
                    OLD_MOUSE_X = (int) event.getX(1);
                    OLD_MOUSE_Y = (int) event.getY(1);
                    break;
                case 1:
                    OLD_MOUSE_X = (int) event.getX(0);
                    OLD_MOUSE_Y = (int) event.getY(0);
                    break;
            }
            break;
    }
    return true;
}

private float calcDistance(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return FloatMath.sqrt(x * x + y * y);
}

private void calcMidpoint(MotionEvent event) {
    centerX = (int) ((event.getX(0) + event.getX(1)) / 2);
    centerY = (int) ((event.getY(0) + event.getY(1)) / 2);
}

// the implementation of the renderer interface
private class OurRenderer implements GLSurfaceView.Renderer {

    //Declaration of some variables for our planets and moons
    private Sphere sun;
    private Sphere merkur;
    private Sphere venus;
    private Sphere erde;
    private Sphere neptun;
    private Sphere uranus;
    private Sphere saturn; 
    private Sphere jupiter;

    private long milSecPerRotation=20*1000;
    private double angle=0.0f;
    private long lastTime;

    public boolean autoRotate=true;

    public OurRenderer() {

        // Defining our planets and moons

        // spheres along z-axis with lightning
        // radius: the radius of the sphere
        // slices: the number of subdivisions along the z-axis
        // stacks: the number of subdivisions around the z-axis
        sun = new Sphere(4.0f, 10, 10);
        merkur = new Sphere(0.5f, 10,10);
        venus = new Sphere(0.9f, 10,10);
        erde = new Sphere(1.0f, 10,10);
        neptun = new Sphere(1.5f, 10,10);
        uranus = new Sphere(1.5f, 10,10);
        saturn = new Sphere(2.5f, 10,10);
        jupiter = new Sphere(3.0f, 10,10);



    }

    public void onDrawFrame(GL10 gl) {
        // the first thing to do: clear screen and depth buffer
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        // reset modelview matrix
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();

        // set ambient light color
        float model_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
        ByteBuffer bb1 = ByteBuffer.allocateDirect(model_ambient.length * 4);
        bb1.order(ByteOrder.nativeOrder());
        FloatBuffer fb1 = bb1.asFloatBuffer();
        fb1.put(model_ambient);
        fb1.position(0);
        gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, fb1);

        // set light position of LIGHT0
        float light_position[] = { 1.0f, 1.0f, 1.0f, 0.0f };
        ByteBuffer bb2 = ByteBuffer.allocateDirect(light_position.length * 4);
        bb2.order(ByteOrder.nativeOrder());
        FloatBuffer fb2 = bb2.asFloatBuffer();
        fb2.put(light_position);
        fb2.position(0);
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, fb2);

        // enable ligth and lighting
        gl.glEnable(GL10.GL_LIGHT0);
        gl.glEnable(GL10.GL_LIGHTING);

        // manipulate modelview matrix by setting viewing transformation
        gl.glTranslatef(-PAN_X, -PAN_Y, -EYE_DISTANCE);
        Trackball.build_rotmatrix(TRANSFORM_MATRIX, CURRENT_QUATERNION);
        gl.glMultMatrixf(TRANSFORM_MATRIX, 0);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        gl.glColor4x(65536, 0, 0, 65536);

        // create an automatic rotation
        long time = System.currentTimeMillis();
        long deltaTime = time-lastTime;
        lastTime=time;
        if (autoRotate) {
            angle = (float) (angle + 360.0 / milSecPerRotation * 
                                                                       deltaTime);
            if (angle > 360.0f)
                angle -= 360;

        }    


        //Building the planets and moons and defining position, rotation and 
                  color

        gl.glPushMatrix();
            gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
            sun.draw(gl);
        gl.glPopMatrix();
        gl.glPushMatrix();
            gl.glTranslatef(0.0f, 8.0f, 0.0f);
            gl.glRotatef((float) angle, 0.0f, 0.0f, -1.0f);
            merkur.draw(gl);
            gl.glPopMatrix();
        gl.glPushMatrix();
            gl.glTranslatef(0.0f, 16.0f, 0.0f);
            gl.glRotatef((float) angle, 0.0f, 0.0f, -1.0f);
            venus.draw(gl);
        gl.glPopMatrix();
        gl.glPushMatrix();
            gl.glTranslatef(0.0f, 24.0f, 0.0f);
            gl.glRotatef((float) angle, 0.0f, 0.0f, -1.0f);
            erde.draw(gl);
        gl.glPopMatrix();
        gl.glPushMatrix();
            gl.glTranslatef(0.0f, 32.0f, 0.0f);
            gl.glRotatef((float) angle, 0.0f, 0.0f, -1.0f);
            neptun.draw(gl);
        gl.glPopMatrix();
        gl.glPushMatrix();
            gl.glTranslatef(0.0f, 40.0f, 0.0f);
            gl.glRotatef((float) angle, 0.0f, 0.0f, -1.0f);
            uranus.draw(gl);
        gl.glPopMatrix();
        gl.glPushMatrix();
            gl.glTranslatef(0.0f, 48.0f, 0.0f);
            gl.glRotatef((float) angle, 0.0f, 0.0f, -1.0f);
            saturn.draw(gl);
        gl.glPopMatrix();
        gl.glPushMatrix();
            gl.glTranslatef(0.0f, 56.0f, 0.0f);
            gl.glRotatef((float) angle, 0.0f, 0.0f, -1.0f);
            jupiter.draw(gl);
        gl.glPopMatrix();
    }

    // resize of viewport
    // set projection matrix
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);

        float aspectRatio = (float) width / height;
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        GLU.gluPerspective(gl, 45.0f, aspectRatio, zNear, zFar);
        GLU.gluLookAt(gl, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 
                                                                             0.0f);
        gl.glMatrixMode(GL10.GL_MODELVIEW);

        lastTime = System.currentTimeMillis();
    }

    // creation of viewport
    // initialization of some opengl features
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        gl.glDisable(GL10.GL_DITHER);
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

        gl.glClearColor(0, 0, 0, 1);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glShadeModel(GL10.GL_SMOOTH);
        //gl.glShadeModel(GL10.GL_FLAT);
        gl.glEnable(GL10.GL_DEPTH_TEST);

        resetViewing();
    }
}

// reset of view parameters
static void resetViewing() {
    EYE_DISTANCE = 0.5f;
    EYE_DISTANCE_INC = 0.5f;
    PAN_X = 0.0f;
    PAN_Y = 0.0f;
    PAN_INC = 0.1f;

    // trackball init
    Trackball.trackball(CURRENT_QUATERNION, 0.0f, 0.0f, 0.0f, 0.0f);
}
}
4

1 に答える 1

1

球を惑星のように動かすには、回転してから平行移動します。

glPushMatrix();
  gluLookAt( ... );  // The camera transformation should affect everyone
  sun.draw(gl);

  // Draw the earth and moon
  glPushMatrix();
    glRotatef( day, 0, 1, 0 );
    glTranslatef( 0, earthRadius, 0 );
    glPushMatrix();
      glRotatef( hour, 0, 1, 0 );
      earth.draw(gl);
      glTranslatef( 0, moonRadius, 0 );
      moon.draw(gl); // the moon is geostationary, so it doesn't rotate
    glPopMatrix();
  glPopMatrix();

  // Draws mars
  glPushMatrix();
    glRotatef( martianDay, 0, 1, 0 );
    glTranslatef( 0, marsRadius, 0 );
    mars.draw(gl);
  glPopMatrix();

glPopMatrix();

glPushMatrix/glPopMatrixこの一連の呼び出しは、「依存変換」と呼ばれることがよくあります。これは、変換のアクションが、後で同じブロック内にあるときに呼び出される変換に影響を与えるためです。

色の問題については、ライティングが有効になっていて、ライティングから生成された色が(OpenGL内で、頂点配列ではなく)頂点とともに渡されるためです。それ自体は問題ではありませんが、ライトモデルのアンビエント部分を有効にする以上のことが必要です。具体的には、オブジェクトのマテリアルプロパティを指定する必要があります。を見てくださいglMaterialf

于 2013-01-24T03:46:27.537 に答える