SpinWorld! in Android , 3D version

Xikh
Xikh
Published in
6 min readSep 24, 2018

Take 1 :

Objective of the simple mission is to Spin a 3D World in Android.

Here is the code.

``` dart
package app.softwares.helloworld;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/// Include these requirements in your AndroidManifest.xml file
/// <!-- Tell the system this app requires OpenGL ES 2.0. -->
/// <uses-feature android:glEsVersion="0x00020000" android:required="true" />
import android.opengl.GLES20;
/// If your application uses texture compression formats, you must declare the formats your application supports in your manifest file using <supports-gl-texture>.
/// See Texture compression support
public class SpinworldPlugin implements MethodCallHandler {
/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "spinworld");
channel.setMethodCallHandler(new SpinworldPlugin());
}

@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
}
}
``` java
public class SpinWorldActivity extends Activity {
private GLSurfaceView mGLView;@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a GLSurfaceView instance and set it
// as the ContentView for this Activity.
mGLView = new MyGLSurfaceView(this);
setContentView(mGLView);
}
}
class MyGLSurfaceView extends GLSurfaceView {private final MyGLRenderer mRenderer;public MyGLSurfaceView(Context context){
super(context);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
mRenderer = new MyGLRenderer();/// ROTATE SHAPE - COMMENT OUT FLAGS
// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // Old

// Render the view only when there is a change in the drawing data.
// To allow the triangle to rotate automatically, this line is commented out:
//setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // New
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(mRenderer);

}
}
public class MyGLRenderer implements GLSurfaceView.Renderer {
/// DRAWING SHAPES
private Triangle mTriangle;
private Square mSquare;

/// DEFINING PROJECTION
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

/// DRAWING SHAPES
// initialize a triangle
mTriangle = new Triangle();
// initialize a square
mSquare = new Square();
}/// ROTATE SHAPE
private float[] mRotationMatrix = new float[16];
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

/// DRAWING SHAPES
mTriangle.draw();

/// DEFINING CAMERA VIEW
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

/// ROTATE SHAPE
float[] scratch = new float[16];
// Create a rotation transformation for the triangle
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, angle, 0, 0, -1.0f);
// Combine the rotation matrix with the projection and camera view
// Note that the mMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

/// ROTATE SHAPE - OLD CODE COMMENTED
// Calculate the projection and view transformation
// Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// Draw shape
mTriangle.draw(mMVPMatrix);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);

/// DEFINING PROJECTION
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}

/// DRAWING SHAPES - SHADER UTILITY
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
/// DEFINING SHAPES
public class Triangle {
private FloatBuffer vertexBuffer;

/// DRAWING SHAPES
private final int mProgram;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = { // in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);

/// DRAWING SHAPES
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);

// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
private int mPositionHandle;
private int mColorHandle;
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);

/// APPLY PROJECTION AND CAMERA TRANSFORMS
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}}

/// DRAWING SHAPES - SHADERS
/// APPLY PROJECTION AND CAMERA TRANSFORMS
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
//" gl_Position = vPosition;" + // Old
" gl_Position = uMVPMatrix * vPosition;" + // New
"}";

// Use to access and set the view transformation
private int mMVPMatrixHandle;
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
}public class Square {private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float squareCoords[] = {
-0.5f, 0.5f, 0.0f, // top left
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f, // bottom right
0.5f, 0.5f, 0.0f }; // top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw verticespublic Square() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
}
}

Thanks for your contribution paypal.me/xikh in helping us live the world.

The triangles has to create a 3D world

Lifted from my friend https://codepen.io/Mamboleoo Louis

``` javascript...var positions = [];
for (var x = 0; x < 5000; x++) {
var pos = {
x: Math.random(),
y: Math.random(),
z: Math.random(),
lat : 2 * Math.PI * Math.random(),
long : Math.acos(2 * Math.random() - 1)
};
pos.u = Math.cos(pos.long);
pos.sqrt = Math.sqrt(1 - (pos.u*pos.u));
positions.push(pos);
}
...galaxy = new THREE.Object3D();
scene.add(galaxy);

controls = new THREE.TrackballControls(camera, renderer.domElement);
var loader = new THREE.TextureLoader();
loader.crossOrigin = "";
var loader2 = new THREE.TextureLoader();
loader2.crossOrigin = "";
dotTexture = loader2.load("https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/dotTexture.png");

dotsMaterial = new THREE.PointsMaterial({
size: userData.dotsSize,
map: dotTexture,
transparent: true,
opacity:userData.dotsOpacity,
alphaTest: 0.1
});

strokesMaterial = new THREE.LineBasicMaterial({
color: 0xffffff,
transparent:true,
opacity:userData.linesOpacity
});
strokes = new THREE.LineSegments(new THREE.Geometry(), strokesMaterial);
galaxy.add(strokes);
dotStrokes = new THREE.Points(new THREE.Geometry(), dotsMaterial);
galaxy.add(dotStrokes);

createStrokes();
requestAnimationFrame(render);
}
var particlesRandom = [];function createStrokes() {
var dots = new THREE.Geometry();
// Create vertices
for (var i = 0; i < userData.amount; i++) {
var pos = {
x: (positions[i].x*userData.height + userData.radius) * positions[i].sqrt * Math.cos(positions[i].lat),
y: (positions[i].y*userData.height + userData.radius) * positions[i].sqrt * Math.sin(positions[i].lat),
z: (positions[i].z*userData.height + userData.radius) * positions[i].u
};
var vector = new THREE.Vector3(pos.x, pos.y, pos.z);
vector.amount = 0;
dots.vertices.push(vector);
}

// Create segments
var segments = new THREE.Geometry();
for(var i=dots.vertices.length-1;i>=0;i--){
var vector = dots.vertices[i];
for(var j=dots.vertices.length-1;j>=0;j--){
if(vector.amount < userData.connections && i!==j && vector.distanceTo(dots.vertices[j]) < userData.distance){
segments.vertices.push(vector);
segments.vertices.push(dots.vertices[j]);
vector.amount++;
dots.vertices[j].amount++;
}
}
}

strokesMaterial.opacity = userData.linesOpacity;
strokesMaterial.color = new THREE.Color(userData.strokesColor);
strokes.geometry = segments;

if(userData.dots){
dotsMaterial.size = userData.dotsSize;
dotsMaterial.opacity = userData.dotsOpacity;
dotsMaterial.color = new THREE.Color(userData.dotsColor);
dotStrokes.geometry = dots;
dotStrokes.geometry.verticesNeedUpdate = true;
} else {
dotsMaterial.opacity = 0;
}

renderer.setClearColor(new THREE.Color(userData.backgroundColor));

Thanks for your contribution paypal.me/xikh in helping us live the world.

--

--

Xikh
Xikh
Editor for

Executive Grade 14 Lateral Hiring Waiting GOI Approval