android立方体

    以前写过一个立方体的主界面,感觉酷酷的,现在分享给大家,效果是这样子的(截图):

     因为当初做的时候要求只能左右滚动,好让立方体图片正的显示出来,所以我把随手势滑动改成左右滑动,每次显示3个面,每个面都可以点击,中间高亮,这样你就可以选择某个面进入你的页面。

    废话少活,来看下项目和代码吧:

 

项目很简单就一个自定义view,一个判断滑动的java文件,然后剩下三个只是为了传值用的观察者模式,你嫌麻烦的话可以直接用handle。

一、先将jpct-ae.jar 复制到libs,右键add as lib那个。

jpce-ae地址:http://www.jpct.net/jpct-ae/

来看一下代码:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.cube.MainActivity">

    <com.example.cube.Cube
        android:id="@+id/cube"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:background="#000"/>

</RelativeLayout>

xml没什么好说的就是一个自定义view。

mainActivity.java:

package com.example.cube;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements CubeObserverListener{
    private Cube cube;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_main);
        cube = (Cube) findViewById(R.id.cube);
        CubeObserverManager.getInstance().add(this);
    }

    @Override
    public void sendMsg(int msg) {
        switch (msg) {
            case 1:
                Toast.makeText(getApplicationContext(), "点击数学", Toast.LENGTH_SHORT).show();
                break;

            case 2:
                Toast.makeText(getApplicationContext(), "点击主页", Toast.LENGTH_SHORT).show();
                break;
            case 3:
                Toast.makeText(getApplicationContext(), "点击消息", Toast.LENGTH_SHORT).show();
                break;
            case 4:
                Toast.makeText(getApplicationContext(), "点击历史", Toast.LENGTH_SHORT).show();
                break;
            case 5:
                Toast.makeText(getApplicationContext(), "点击语文", Toast.LENGTH_SHORT).show();
                break;
            case 6:
                Toast.makeText(getApplicationContext(), "点击设置", Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
    }
}

就是用了观察者模式判断了点击了立方体哪个面做了处理。

主要看一下Render.java和Cube.java这两个

Render.java: 

package com.example.cube;

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

import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Interact2D;
import com.threed.jpct.Light;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

public class Rander implements Renderer{
    public MainActivity mActivity = null;
    private FrameBuffer fb = null;
    private World world = null;
    Camera cam = null;
    // 立方体
    public Object3D cube = null;
    private Object3D a,b,c,d,e,f;
    // 光照类
    private Light sun = null;
    private RGBColor back = new RGBColor(255,228,196);
    // 旋转
    public float touchTurn = 0.28f;
    public float touchTurnUp = 0.9f;
    public float touchTurnRight = 3.8f;
    public boolean isRotate = false;
    public String gride = "none";
    public Rander(Context context) {
        mActivity = (MainActivity) context;
    }
    float m = 0.1f;

    public boolean isTranslation = false;
    public Matrix m1,m2;
    int first = 0;
    @Override
    public void onDrawFrame(GL10 gl) {
        // TODO Auto-generated method stub
        if(Cube.isStart){
            long nowTime = System.currentTimeMillis();
            long deltaTime = nowTime - Cube.startTime;
            long animationInterval=600;
            if(deltaTime>=animationInterval-30 ){
                if(!isTranslation){
                    cube.setRotationMatrix(m2);
                    isTranslation = true;
                }else{
                    cube.setRotationMatrix(m1);
                    isTranslation = false;
                }
                Cube.isStart=false;
            }else{
                float deltaAngle = 0;
                if(gride == "left"){
                    deltaAngle=(float) ((float)((float)deltaTime/animationInterval)*(double)Math.PI);
                }else{
                    deltaAngle=(float) -((float)((float)deltaTime/animationInterval)*(double)Math.PI);
                }
                Matrix toMatrix = Cube.startRotationMatrix.cloneMatrix();
                toMatrix.rotateY(deltaAngle);
                cube.setRotationMatrix(toMatrix);
            }

        }
        fb.clear(back);
        world.renderScene(fb);
        world.draw(fb);
        fb.display();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int w, int h) {
        // TODO Auto-generated method stub
        if (fb != null) {
            fb.dispose();
        }

        // 创建一个宽度为w,高为h的FrameBuffer
        fb = new FrameBuffer(gl, w, h);
    }


    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // TODO Auto-generated method stub
        world = new World();
        world.setAmbientLight(150, 150, 150);  //内部光源

        sun = new Light(world);
        sun.setIntensity(255, 255, 255);
        sun.setPosition( GetPoint( 0, 0, -150));
        sun.setDiscardDistance( 500);

        // 纹理
        CreateTextures();

        // 立方体
        CreateBox();

        // 摄像机
        cam = world.getCamera();
        cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
        cam.lookAt(cube.getTransformedCenter());

        SimpleVector sv = new SimpleVector();
        sv.set(cube.getTransformedCenter());
        sv.x = -1.0f;//外部光源
        sv.y = 1.2f;
        sv.z = -18;
        sun.setPosition(sv);
        MemoryHelper.compact();
        Roate();
    }



    private void Roate() {
        // TODO Auto-generated method stub
        cube.rotateY(touchTurn);
        cube.rotateX(touchTurnUp);
        cube.rotateZ(touchTurnRight);


        m1 = cube.getRotationMatrix();
        m2 = m1.cloneMatrix();
        m2.rotateY((float)Math.PI);
    }


    private SimpleVector GetPoint(int i, int j, int k) {
        // TODO Auto-generated method stub
        SimpleVector sv = new SimpleVector();
        sv.x = i;
        sv.y = j;
        sv.z = k;
        return sv;
    }


    /**
     * 创建纹理
     */
    private void CreateTextures() {
        Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.f)), 128, 128));
        TextureManager.getInstance().addTexture("a", texture);
        texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.a)), 128, 128));
        TextureManager.getInstance().addTexture("b", texture);

        texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.c)), 128, 128));
        TextureManager.getInstance().addTexture("c", texture);

        texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.d)), 128, 128));
        TextureManager.getInstance().addTexture("d", texture);

        texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.e)), 128, 128));
        TextureManager.getInstance().addTexture("e", texture);

        texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.b)), 128, 128));
        TextureManager.getInstance().addTexture("f", texture);
    }

    /**
     * 创建立方体
     */
    private void CreateBox() {
        cube = new Object3D(0);

        // 前
        a = new Object3D(2);
        a.addTriangle(GetPoint(-30, -30, 30), 0.0f, 0.0f,
                GetPoint(30, -30, 30), 1.0f, 0.0f, GetPoint(-30, 30, 30), 0.0f,
                1.0f, TextureManager.getInstance().getTextureID("a"));

        a.addTriangle(GetPoint(30, -30, 30), 1.0f, 0.0f,
                GetPoint(30, 30, 30), 1.0f, 1.0f, GetPoint(-30, 30, 30), 0.0f,
                1.0f, TextureManager.getInstance().getTextureID("a"));
        cube.addChild(a);
        world.addObject(a);
        a.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

        // 上
        b = new Object3D(2);
        b.addTriangle(GetPoint(-30, 30, 30), 0.0f, 0.0f,
                GetPoint(30, 30, 30), 1.0f, 0.0f, GetPoint(-30, 30, -30), 0.0f,
                1.0f, TextureManager.getInstance().getTextureID("b"));

        b.addTriangle(GetPoint(30, 30, 30), 1.0f, 0.0f,
                GetPoint(30, 30, -30), 1.0f, 1.0f, GetPoint(-30, 30, -30),
                0.0f, 1.0f, TextureManager.getInstance().getTextureID("b"));
        cube.addChild(b);
        world.addObject(b);
        b.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

        // 后
        c = new Object3D(2);
        c.addTriangle(GetPoint( -30, 30, -30), 0.0f, 0.0f,
                GetPoint(30, 30, -30), 1.0f, 0.0f, GetPoint(-30, -30, -30),
                0.0f, 1.0f, TextureManager.getInstance().getTextureID("c"));

        c.addTriangle(GetPoint(30, 30, -30), 1.0f, 0.0f,
                GetPoint(30, -30, -30), 1.0f, 1.0f, GetPoint(-30, -30, -30),
                0.0f, 1.0f, TextureManager.getInstance().getTextureID("c"));
        cube.addChild(c);
        world.addObject(c);
        c.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

        // 下
        d = new Object3D(2);
        d.addTriangle(GetPoint(-30, -30, -30), 0.0f, 0.0f,
                GetPoint(30, -30, -30), 1.0f, 0.0f, GetPoint(-30, -30, 30),
                0.0f, 1.0f, TextureManager.getInstance().getTextureID("d"));

        d.addTriangle(GetPoint(30, -30, -30), 1.0f, 0.0f,
                GetPoint(30, -30, 30), 1.0f, 1.0f, GetPoint( -30, -30, 30), 0.0f,
                1.0f, TextureManager.getInstance().getTextureID("d"));
        cube.addChild(d);
        world.addObject(d);
        d.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

        // 左
        e = new Object3D(2);
        e.addTriangle(GetPoint( -30, -30, -30), 0.0f, 0.0f,
                GetPoint(-30, -30, 30), 1.0f, 0.0f, GetPoint(-30, 30, -30),
                0.0f, 1.0f, TextureManager.getInstance().getTextureID("e"));

        e.addTriangle(GetPoint( -30, -30, 30), 1.0f, 0.0f,
                GetPoint(-30, 30, 30), 1.0f, 1.0f, GetPoint(-30, 30, -30),
                0.0f, 1.0f, TextureManager.getInstance().getTextureID("e"));
        cube.addChild(e);
        world.addObject(e);
        e.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

        // 右
        f = new Object3D(2);
        f.addTriangle(GetPoint(30, -30, 30), 0.0f, 0.0f,
                GetPoint(30, -30, -30), 1.0f, 0.0f, GetPoint(30, 30, 30), 0.0f,
                1.0f, TextureManager.getInstance().getTextureID("f"));

        f.addTriangle(GetPoint(30, -30, -30), 1.0f, 0.0f,
                GetPoint(30, 30, -30), 1.0f, 1.0f, GetPoint(30, 30, 30), 0.0f,
                1.0f, TextureManager.getInstance().getTextureID("f"));
        cube.addChild(f);
        world.addObject(f);
        f.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);

        cube.strip();
        cube.build();
        world.addObject(cube);
        cube.setCulling(false);
        cube.scale( 0.25f);
        cube.rotateZ( 100);
        cube.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
    }

    /**
     * 拾取点击事件
     * @param fX
     * @param fY
     * @return
     */
    public int Pickint( int fX, int fY){
        //fY = fb.getHeight() - fY;  
        SimpleVector dir = Interact2D.reproject2D3DWS( cam, fb, fX, fY).normalize();
        Object[] res=world.calcMinDistanceAndObject3D(cam.getPosition(), dir, 10000 );

        Object3D picked = (Object3D)res[1];

        if( picked == null)
            return -1;

        if( picked.getID() == a.getID()) {

            CubeObserverManager.getInstance().notifyObserver(1);
            return 1;
        }
        else  if( picked.getID() == b.getID())  {

            CubeObserverManager.getInstance().notifyObserver(2);
            return 2;
        }
        else  if( picked.getID() == c.getID())  {

            CubeObserverManager.getInstance().notifyObserver(3);
            return 3;
        }
        else  if( picked.getID() == d.getID())  {

            CubeObserverManager.getInstance().notifyObserver(4);
            return 4;
        }
        else  if( picked.getID() == e.getID())  {

            CubeObserverManager.getInstance().notifyObserver(5);
            return 5;  }
        else  if( picked.getID() == f.getID())  {
            CubeObserverManager.getInstance().notifyObserver(6);
            return 6;
        }
        return -1;
    }


    /**
     * 清除纹理
     */
    public void clearTexture() {
        TextureManager.getInstance().removeTexture("a");
        TextureManager.getInstance().removeTexture("b");
        TextureManager.getInstance().removeTexture("c");
        TextureManager.getInstance().removeTexture("d");
        TextureManager.getInstance().removeTexture("e");
        TextureManager.getInstance().removeTexture("f");
    }
}

在onSurfaceCreated的时候绘制立方体及它的纹理,然后就是相机的位置,灯光位置,然后用roate方法设置默认旋转的角度。

在onDrawFrame判断立方体滑动状态,如果滑动到某个时间滑动还没结束就停止滑动,滑动到我预设的那个位置。

Cube.java:

package com.example.cube;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;

import com.threed.jpct.Matrix;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class Cube extends GLSurfaceView {

    private float xpos = -1;
    private float ypos = -1;
    public static long downTime = 0;
    public static long moveTime = 0;
    public static long startTime = 0;
    public static long rotatedTime = 0;

    public static boolean isStart = false;
    public static Matrix startRotationMatrix=new Matrix();
    private Rander mRander;

    public Cube(Context context, AttributeSet attrs) {
        super(context);
        // TODO Auto-generated constructor stub
        // 使用自己实现的 EGLConfigChooser,该实现必须在setRenderer(renderer)之前
        // 如果没有setEGLConfigChooser方法被调用,则默认情况下,视图将选择一个与当前android.view.Surface兼容至少16位深度缓冲深度EGLConfig。
        setEGLConfigChooser(new EGLConfigChooser() {
            public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
                int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16,
                        EGL10.EGL_NONE };
                EGLConfig[] configs = new EGLConfig[1];
                int[] result = new int[1];
                egl.eglChooseConfig(display, attributes, configs, 1, result);
                return configs[0];
            }
        });
        mRander = new Rander(context);
        setRenderer(mRander);

    }


    public boolean onTouchEvent(MotionEvent me) {
        if (me.getAction() == MotionEvent.ACTION_DOWN) {
            mRander.Pickint( (int)me.getX(), (int)me.getY());
            downTime = System.currentTimeMillis();
            xpos = me.getX();
            ypos = me.getY();
            mRander.isRotate = false;
            return true;
        }

        if (me.getAction() == MotionEvent.ACTION_UP) {
            mRander.isRotate = false;
            xpos = -1;
            ypos = -1;
            return true;
        }

        if (me.getAction() == MotionEvent.ACTION_MOVE) {
            mRander.isRotate = true;
            float xd = me.getX() - xpos;
            float yd = me.getY() - ypos;
            xpos = me.getX();
            ypos = me.getY();
            if(xd >30){//右
                mRander.gride = "right";
                startRotationMatrix=mRander.cube.getRotationMatrix();
                startTime = System.currentTimeMillis();
                isStart = true;

            }else if(xd<-30){//左
                mRander.gride = "left";
                startRotationMatrix=mRander.cube.getRotationMatrix();
                startTime = System.currentTimeMillis();
                isStart = true;
            }
            Cube.this.setEnabled(false);
            Cube.this.clearFocus();
            return true;
        }

        try {
            Thread.sleep(15);
        } catch (Exception e) {
            // No need for this...  
        }

        return super.onTouchEvent(me);
    }
    
    public void clearTexture() {
        if(mRander != null){
            mRander.clearTexture();
        }
    }
    
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        clearTexture();
    }
}

 处理一下滑动。

CubeObserverManager.java:
package com.example.cube;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by wanghk on 2018-09-27.
 */

public class CubeObserverManager implements CubeSubjectListener {

    private static CubeObserverManager manager;
    private List<CubeObserverListener> list = new ArrayList<>();

    public static CubeObserverManager getInstance(){
        if(null == manager){
            synchronized (CubeObserverManager.class){
                if(null == manager)
                manager = new CubeObserverManager();
            }
        }
        return manager;
    }

    @Override
    public void add(CubeObserverListener observerListener) {
        list.add(observerListener);
    }

    @Override
    public void notifyObserver(int msg) {
        for (CubeObserverListener observerListener : list){
             observerListener.sendMsg(msg);
        }
    }

    @Override
    public void remove(CubeObserverListener observerListener) {
        if(list.contains(observerListener))
            list.remove(observerListener);
    }
}
CubeSubjectListener.java:
package com.example.cube;

/**
 * Created by wanghk on 2018-09-27.
 */

public interface CubeSubjectListener {
    void add(CubeObserverListener observerListener);
    void notifyObserver(int msg);
    void remove(CubeObserverListener observerListener);
}
CubeObserverListener.java:
package com.example.cube;

/**
 * Created by wanghk on 2018-09-27.
 * 观察者接口
 */

public interface CubeObserverListener {
    void sendMsg(int msg);
}

这三个java只是为了传递点击哪个面而已。

就是这些了,代码里几乎都有注释。效果就是左右滑动的立方体。有什么问题欢迎询问QQ:1398169857。

项目链接:https://pan.baidu.com/s/14JgzwiCktc5nlzrxTH9SXA 
提取码:x9dw 

发布了14 篇原创文章 · 获赞 23 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_27378951/article/details/85050310