chenyoufu.hciprojectes10.MyGLSurfaceView.java Source code

Java tutorial

Introduction

Here is the source code for chenyoufu.hciprojectes10.MyGLSurfaceView.java

Source

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package chenyoufu.hciprojectes10;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.opengl.GLSurfaceView;
import android.support.v4.view.MotionEventCompat;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.Vector;

/**
 * A view container where OpenGL ES graphics can be drawn on screen.
 * This view can also be used to capture touch events, such as a user
 * interacting with drawn objects.
 */
public class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer mRenderer;
    private ScaleGestureDetector mScaleDetector;

    private void readMesh() {
        try {
            InputStream meshIS = getResources().openRawResource(R.raw.eight);
            BufferedReader meshReader = new BufferedReader(new InputStreamReader(meshIS, "UTF-8"));
            String line;
            boolean isVertex = false;
            boolean isFace = false;
            while ((line = meshReader.readLine()) != null) {
                if (!isVertex && !isFace) {
                    if (line.charAt(0) == 'V') {
                        Global.verticesCount++;
                        isVertex = true;
                    }
                } else if (isFace) {
                    Global.facesCount++;
                } else {
                    if (line.charAt(0) == 'F') {
                        Global.facesCount++;
                        isFace = true;
                    } else {
                        Global.verticesCount++;
                    }
                }
            }
            meshReader.close();
            meshIS.close();

            Global.edgesCount = 3 * Global.facesCount;

            //vertices.setSize(verticesCount);
            //faces.setSize(facesCount);
            //edges.setSize(edgesCount);
            for (int i = 0; i < Global.edgesCount; i++)
                Global.edges.add(new HEEdge(null, null, null, null, null));

            // main loop, to assign elements to lists.
            //int vertexNum=0; // count from 1
            int faceNum = 0; // count from 1
            //int edgeNum=0; // count from 1
            // restore loop state
            isVertex = false;
            isFace = false;

            meshIS = getResources().openRawResource(R.raw.eight);
            meshReader = new BufferedReader(new InputStreamReader(meshIS, "UTF-8"));
            while ((line = meshReader.readLine()) != null) {
                if (!isFace && !isVertex) {
                    if (line.charAt(0) == 'V') {
                        float x = 0, y = 0, z = 0;
                        // fist vertex
                        String[] split = line.split("\\s+");
                        x = Float.parseFloat(split[2]);
                        y = Float.parseFloat(split[3]);
                        z = Float.parseFloat(split[4]);
                        Global.vertices.add(new HEVert(x, y, z, null));
                        // loop
                        isVertex = true;
                    }
                } else if (isFace) {
                    int v1 = 0, v2 = 0, v3 = 0;
                    String[] split = line.split("\\s+");
                    faceNum = Integer.parseInt(split[1]);
                    v1 = Integer.parseInt(split[2]);
                    v2 = Integer.parseInt(split[3]);
                    v3 = Integer.parseInt(split[4]);

                    Global.faces.add(new HEFace(Global.edges.get(faceNum * 3 - 3)));

                    Global.vertices.get(v1 - 1).edge = Global.edges.get(faceNum * 3 - 3);
                    Global.vertices.get(v2 - 1).edge = Global.edges.get(faceNum * 3 - 2);
                    Global.vertices.get(v3 - 1).edge = Global.edges.get(faceNum * 3 - 1);

                    Global.edges.get(faceNum * 3 - 3).vert = Global.vertices.get(v1 - 1);
                    Global.edges.get(faceNum * 3 - 3).face = Global.faces.get(faceNum - 1);
                    Global.edges.get(faceNum * 3 - 3).prev = Global.edges.get(faceNum * 3 - 1);
                    Global.edges.get(faceNum * 3 - 3).next = Global.edges.get(faceNum * 3 - 2);

                    Global.edges.get(faceNum * 3 - 2).vert = Global.vertices.get(v2 - 1);
                    Global.edges.get(faceNum * 3 - 2).face = Global.faces.get(faceNum - 1);
                    Global.edges.get(faceNum * 3 - 2).prev = Global.edges.get(faceNum * 3 - 3);
                    Global.edges.get(faceNum * 3 - 2).next = Global.edges.get(faceNum * 3 - 1);

                    Global.edges.get(faceNum * 3 - 1).vert = Global.vertices.get(v3 - 1);
                    Global.edges.get(faceNum * 3 - 1).face = Global.faces.get(faceNum - 1);
                    Global.edges.get(faceNum * 3 - 1).prev = Global.edges.get(faceNum * 3 - 2);
                    Global.edges.get(faceNum * 3 - 1).next = Global.edges.get(faceNum * 3 - 3);

                    Global.edgesTemp.put((v1 - 1) + "-" + (v2 - 1), faceNum * 3 - 3);
                    Global.edgesTemp.put((v2 - 1) + "-" + (v3 - 1), faceNum * 3 - 2);
                    Global.edgesTemp.put((v3 - 1) + "-" + (v1 - 1), faceNum * 3 - 1);

                    // dealing with pair edge

                    Integer value = Global.edgesTemp.get("" + (v2 - 1) + "-" + (v1 - 1));
                    if (value != null) {
                        Global.edges.get(faceNum * 3 - 3).pair = Global.edges.get(value);
                        Global.edges.get(value).pair = Global.edges.get(faceNum * 3 - 3);
                    }
                    value = Global.edgesTemp.get("" + (v3 - 1) + "-" + (v2 - 1));
                    if (value != null) {
                        Global.edges.get(faceNum * 3 - 2).pair = Global.edges.get(value);
                        Global.edges.get(value).pair = Global.edges.get(faceNum * 3 - 2);
                    }
                    value = Global.edgesTemp.get("" + (v1 - 1) + "-" + (v3 - 1));
                    if (value != null) {
                        Global.edges.get(faceNum * 3 - 1).pair = Global.edges.get(value);
                        Global.edges.get(value).pair = Global.edges.get(faceNum * 3 - 1);
                    }
                } else { // is_vertex
                    if (line.charAt(0) == 'F') {
                        // first face
                        int v1 = 0, v2 = 0, v3 = 0;
                        String[] split = line.split("\\s+");
                        faceNum = Integer.parseInt(split[1]);
                        v1 = Integer.parseInt(split[2]);
                        v2 = Integer.parseInt(split[3]);
                        v3 = Integer.parseInt(split[4]);

                        Global.faces.add(new HEFace(Global.edges.get(faceNum * 3 - 3)));

                        Global.vertices.get(v1 - 1).edge = Global.edges.get(faceNum * 3 - 3);
                        Global.vertices.get(v2 - 1).edge = Global.edges.get(faceNum * 3 - 2);
                        Global.vertices.get(v3 - 1).edge = Global.edges.get(faceNum * 3 - 1);

                        Global.edges.get(faceNum * 3 - 3).vert = Global.vertices.get(v1 - 1);
                        Global.edges.get(faceNum * 3 - 3).face = Global.faces.get(faceNum - 1);
                        Global.edges.get(faceNum * 3 - 3).prev = Global.edges.get(faceNum * 3 - 1);
                        Global.edges.get(faceNum * 3 - 3).next = Global.edges.get(faceNum * 3 - 2);

                        Global.edges.get(faceNum * 3 - 2).vert = Global.vertices.get(v2 - 1);
                        Global.edges.get(faceNum * 3 - 2).face = Global.faces.get(faceNum - 1);
                        Global.edges.get(faceNum * 3 - 2).prev = Global.edges.get(faceNum * 3 - 3);
                        Global.edges.get(faceNum * 3 - 2).next = Global.edges.get(faceNum * 3 - 1);

                        Global.edges.get(faceNum * 3 - 1).vert = Global.vertices.get(v3 - 1);
                        Global.edges.get(faceNum * 3 - 1).face = Global.faces.get(faceNum - 1);
                        Global.edges.get(faceNum * 3 - 1).prev = Global.edges.get(faceNum * 3 - 2);
                        Global.edges.get(faceNum * 3 - 1).next = Global.edges.get(faceNum * 3 - 3);

                        Global.edgesTemp.put((v1 - 1) + "-" + (v2 - 1), faceNum * 3 - 3);
                        Global.edgesTemp.put((v2 - 1) + "-" + (v3 - 1), faceNum * 3 - 2);
                        Global.edgesTemp.put((v3 - 1) + "-" + (v1 - 1), faceNum * 3 - 1);
                        // loop
                        isFace = true;
                    } else {
                        float x = 0, y = 0, z = 0;
                        String[] split = line.split("\\s+");
                        x = Float.parseFloat(split[2]);
                        y = Float.parseFloat(split[3]);
                        z = Float.parseFloat(split[4]);
                        Global.vertices.add(new HEVert(x, y, z, null));
                    }
                }
            }
            meshReader.close();
            meshIS.close();

            // Calculate bounding box
            float tempMinX = Float.MAX_VALUE, tempMinY = Float.MAX_VALUE, tempMinZ = Float.MAX_VALUE;
            float tempMaxX = Float.MIN_VALUE, tempMaxY = Float.MIN_VALUE, tempMaxZ = Float.MIN_VALUE;
            for (int i = 0; i < Global.verticesCount; i++) {
                if (Global.vertices.get(i).x > tempMaxX)
                    tempMaxX = Global.vertices.get(i).x;
                if (Global.vertices.get(i).y > tempMaxY)
                    tempMaxY = Global.vertices.get(i).y;
                if (Global.vertices.get(i).z > tempMaxZ)
                    tempMaxZ = Global.vertices.get(i).z;
                if (Global.vertices.get(i).x < tempMinX)
                    tempMinX = Global.vertices.get(i).x;
                if (Global.vertices.get(i).y < tempMinY)
                    tempMinY = Global.vertices.get(i).y;
                if (Global.vertices.get(i).z < tempMinZ)
                    tempMinZ = Global.vertices.get(i).z;
            }
            Global.maxX = tempMaxX;
            Global.minX = tempMinX;
            Global.maxY = tempMaxY;
            Global.minY = tempMinY;
            Global.maxZ = tempMaxZ;
            Global.minZ = tempMinZ;

            // Normalize the vertex coordinates (in the range of 0~2)
            float centroidX = (Global.maxX + Global.minX) / 2;
            float rangeX = Global.maxX - centroidX;
            float centroidY = (Global.maxY + Global.minY) / 2;
            float rangeY = Global.maxY - centroidY;
            float centroidZ = (Global.maxZ + Global.minZ) / 2;
            float rangeZ = Global.maxZ - centroidZ;
            float tempRange;
            float maxRatio = (tempRange = rangeX > rangeY ? rangeX : rangeY) > rangeZ ? tempRange : rangeZ;
            for (int i = 0; i < Global.verticesCount; i++) {
                Global.vertices.get(i).x = (Global.vertices.get(i).x - (Global.minX + Global.maxX) / 2) / maxRatio;
                Global.vertices.get(i).y = (Global.vertices.get(i).y - (Global.minY + Global.maxY) / 2) / maxRatio;
                Global.vertices.get(i).z = (Global.vertices.get(i).z - (Global.minZ + Global.maxZ) / 2) / maxRatio;
            }

            /*for (int i=0; i< Global.verticesCount; i++) {
            System.out.println(i+" "+Global.vertices.get(i).edge.face.edge.vert.x);
            }*/

            /*Global.maxX=(Global.maxX-Global.minX)/maxRatio;Global.minX=0;
            Global.maxY=(Global.maxY-Global.minY)/maxRatio;Global.minY=0;
            Global.maxZ=(Global.maxZ-Global.minZ)/maxRatio;Global.minZ=0;*/

            // Compute face normals & vertex normals
            for (int i = 0; i < Global.facesCount; i++) {
                Tuple3 v1 = new Tuple3(Global.faces.get(i).edge.vert);
                Tuple3 v2 = new Tuple3(Global.faces.get(i).edge.next.vert);
                Tuple3 v3 = new Tuple3(Global.faces.get(i).edge.prev.vert);
                Tuple3 e1 = new Tuple3(v2.x - v1.x, v2.y - v1.y, v2.z - v1.z);
                Tuple3 e2 = new Tuple3(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z);
                Tuple3 tempNormal = new Tuple3(e1.y * e2.z - e1.z * e2.y, e1.z * e2.x - e1.x * e2.z,
                        e1.x * e2.y - e1.y * e2.x);
                float tempArea = (float) Math.sqrt(
                        tempNormal.x * tempNormal.x + tempNormal.y * tempNormal.y + tempNormal.z * tempNormal.z);
                Global.faceInfos.put(Global.faces.get(i), new FaceInfo(tempArea, tempNormal));
            }
            for (int i = 0; i < Global.verticesCount; i++) {

                HEFace faceNow = Global.vertices.get(i).edge.face;
                float totalArea = Global.faceInfos.get(faceNow).area;
                Tuple3 tempNormal = Global.faceInfos.get(faceNow).normal.mul(totalArea);
                Global.vertexNormals.put(Global.vertices.get(i), tempNormal);
                HEEdge edgeNow = Global.vertices.get(i).edge;
                boolean isReverse = false;
                while (true) {
                    if (!isReverse) {
                        if (edgeNow.pair != null) {
                            if (edgeNow.pair.next != Global.vertices.get(i).edge) {
                                edgeNow = edgeNow.pair.next;
                                Global.vertexNormals
                                        .get(Global.vertices.get(i)).x += Global.faceInfos.get(edgeNow.face).area
                                                * Global.faceInfos.get(edgeNow.face).normal.x;
                                Global.vertexNormals
                                        .get(Global.vertices.get(i)).y += Global.faceInfos.get(edgeNow.face).area
                                                * Global.faceInfos.get(edgeNow.face).normal.y;
                                Global.vertexNormals
                                        .get(Global.vertices.get(i)).z += Global.faceInfos.get(edgeNow.face).area
                                                * Global.faceInfos.get(edgeNow.face).normal.z;
                                totalArea += Global.faceInfos.get(edgeNow.face).area;
                            } else
                                break;
                        } else {
                            isReverse = true;
                            edgeNow = Global.vertices.get(i).edge;
                        }
                    } else {
                        if (edgeNow.prev.pair != null) {
                            edgeNow = edgeNow.prev.pair;
                            Global.vertexNormals
                                    .get(Global.vertices.get(i)).x += Global.faceInfos.get(edgeNow.face).area
                                            * Global.faceInfos.get(edgeNow.face).normal.x;
                            Global.vertexNormals
                                    .get(Global.vertices.get(i)).y += Global.faceInfos.get(edgeNow.face).area
                                            * Global.faceInfos.get(edgeNow.face).normal.y;
                            Global.vertexNormals
                                    .get(Global.vertices.get(i)).z += Global.faceInfos.get(edgeNow.face).area
                                            * Global.faceInfos.get(edgeNow.face).normal.z;
                            totalArea += Global.faceInfos.get(edgeNow.face).area;
                        } else
                            break;
                    }
                }
                Global.vertexNormals.get(Global.vertices.get(i)).x /= totalArea;
                Global.vertexNormals.get(Global.vertices.get(i)).y /= totalArea;
                Global.vertexNormals.get(Global.vertices.get(i)).z /= totalArea;

                //Global.normalize(Global.vertexNormals.get(Global.vertices.get(i)));
            }

            /*for (int i=0; i< Global.verticesCount;i++) {
            System.out.println(Math.sqrt(Global.vertexNormals.get(Global.vertices.get(i)).x*Global.vertexNormals.get(Global.vertices.get(i)).x+Global.vertexNormals.get(Global.vertices.get(i)).y*Global.vertexNormals.get(Global.vertices.get(i)).y+Global.vertexNormals.get(Global.vertices.get(i)).z*Global.vertexNormals.get(Global.vertices.get(i)).z));
            }*/
            /*for (int i=0; i< Global.verticesCount; i++){
            System.out.println(i+" "+Global.vertexNormals.get(Global.vertices.get(i)).x+" "+Global.vertexNormals.get(Global.vertices.get(i)).y+" "+Global.vertexNormals.get(Global.vertices.get(i)).z);
            }*/

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public MyGLSurfaceView(Context context) {
        super(context);

        readMesh();

        // Set the Renderer for drawing on the GLSurfaceView
        mRenderer = new MyGLRenderer();
        setRenderer(mRenderer);

        // Render the view only when there is a change in the drawing data
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {

            float sf = detector.getScaleFactor();
            Global.cameraEye[0] += (sf - 1) * (Global.cameraCentre[0] - Global.cameraEye[0]);
            Global.cameraEye[1] += (sf - 1) * (Global.cameraCentre[1] - Global.cameraEye[1]);
            Global.cameraEye[2] += (sf - 1) * (Global.cameraCentre[2] - Global.cameraEye[2]);

            invalidate();
            return true;
        }
    }

    private float xOri = -1;
    private float yOri = -1;

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = MotionEventCompat.getActionMasked(event);
        int index = MotionEventCompat.getActionIndex(event);

        if (event.getPointerCount() > 1) {
            if (action == MotionEvent.ACTION_POINTER_UP && event.getPointerCount() == 2) {
                xOri = MotionEventCompat.getX(event, 1 - index);
                yOri = MotionEventCompat.getY(event, 1 - index);
            }
            mScaleDetector.onTouchEvent(event);
        } else {
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                xOri = MotionEventCompat.getX(event, index);
                yOri = MotionEventCompat.getY(event, index);

                break;
            case MotionEvent.ACTION_MOVE:
                float xNow = MotionEventCompat.getX(event, index);
                float yNow = MotionEventCompat.getY(event, index);

                float[] xMove = Global.fArrayMul(Global.getCamCrossProductNV(), (xOri - xNow) / Global.moveFactor);
                Global.cameraEye = Global.fArrayAdd(Global.cameraEye, xMove);
                Global.cameraCentre = Global.fArrayAdd(Global.cameraCentre, xMove);
                float[] yMove = Global.fArrayMul(Global.cameraUp, (yNow - yOri) / Global.moveFactor);
                Global.cameraEye = Global.fArrayAdd(Global.cameraEye, yMove);
                Global.cameraCentre = Global.fArrayAdd(Global.cameraCentre, yMove);
                xOri = xNow;
                yOri = yNow;
                break;
            default:
                break;
            }
        }
        requestRender();
        return true;
    }

}