Browse Source

added bee with procedural animation

Fabio Arnold 10 years ago
parent
commit
ac612758f7

BIN
assets/meshes/android.amh


BIN
assets/meshes/bee.amh


+ 6 - 3
assets/shaders/skinned.frag

@@ -1,13 +1,16 @@
 precision mediump float;
 
 uniform vec4 color;
+uniform sampler2D texture;
 
 varying vec3 vertexNormal;
+varying vec2 vertexTexCoord;
 
 void main() {
 	vec3 normal = normalize(vertexNormal);
-	float lambert = max(0.0, -normal.y);
+	float lambert = max(0.0, -normal.z);
 	float rim = 1.0 - lambert;
 	rim *= rim * rim;
-	gl_FragColor = rim + (0.4 + 0.4 * lambert) * color;
-}
+	vec4 texColor = texture2D(texture, vertexTexCoord);
+	gl_FragColor = rim + (0.4 + 0.4 * lambert) * texColor * color;
+}

+ 4 - 1
assets/shaders/skinned.vert

@@ -3,11 +3,13 @@ uniform mat4 boneMatrices[16];
 
 attribute vec3 position;
 attribute vec3 normal;
+attribute vec2 texCoord;
 
 attribute vec4 boneIndices; // should be ivec4
 attribute vec3 boneWeights;
 
 varying vec3 vertexNormal;
+varying vec2 vertexTexCoord;
 
 void main() {
 	float fourthBoneWeight = 1.0 - boneWeights[0] - boneWeights[1] - boneWeights[2];
@@ -17,6 +19,7 @@ void main() {
 	boneMatrix += boneWeights[2] * boneMatrices[int(boneIndices.z)];
 	boneMatrix += fourthBoneWeight * boneMatrices[int(boneIndices.w)];
 
-	vertexNormal = mat3(boneMatrix) * normal;
+	vertexNormal = mat3(mvp) * mat3(boneMatrix) * normal;
+	vertexTexCoord = texCoord;
 	gl_Position = mvp * boneMatrix * vec4(position, 1.0);
 }

BIN
assets/textures/android-tex.png


BIN
assets/textures/bee-tex.png


+ 1 - 0
src/de/tudarmstadt/informatik/hostage/ui2/activity/MainActivity.java

@@ -50,6 +50,7 @@ public class MainActivity extends Activity {
         MainActivity.context = getApplicationContext();
         
         ThreatIndicatorGLRenderer.assets = getAssets();
+        ThreatIndicatorGLRenderer.setThreatLevel(0);
 
         setContentView(R.layout.activity_drawer_main);
 

+ 5 - 3
src/de/tudarmstadt/informatik/hostage/ui2/fragment/opengl/AnimatedMesh.java

@@ -231,10 +231,8 @@ public class AnimatedMesh {
 		return v3;
 	}
 
-	static boolean toggle = true;
 	public void tick() {
-		toggle = !toggle; // very clever (!) way to slow the animation :DDDD
-		if (toggle) currentFrame++;
+		currentFrame++;
 		if (currentFrame >= currentAction.numFrames)
 			currentFrame = 0;
 		
@@ -268,11 +266,13 @@ public class AnimatedMesh {
 		// TODO: cache attrib locations
 		int positionIndex = GLES20.glGetAttribLocation(program, "position");
 		int normalIndex = GLES20.glGetAttribLocation(program, "normal");
+		int texCoordIndex = GLES20.glGetAttribLocation(program, "texCoord");
 		int boneIndicesIndex = GLES20.glGetAttribLocation(program, "boneIndices");
 		int boneWeightsIndex = GLES20.glGetAttribLocation(program, "boneWeights");
 		
 		GLES20.glEnableVertexAttribArray(positionIndex);
 		GLES20.glEnableVertexAttribArray(normalIndex);
+		GLES20.glEnableVertexAttribArray(texCoordIndex);
 		GLES20.glEnableVertexAttribArray(boneIndicesIndex);
 		GLES20.glEnableVertexAttribArray(boneWeightsIndex);
 		
@@ -281,6 +281,7 @@ public class AnimatedMesh {
 		GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
 		GLES20.glVertexAttribPointer(positionIndex, 3, GLES20.GL_FLOAT, false, vertexSize, 0);
 		GLES20.glVertexAttribPointer(normalIndex, 3, GLES20.GL_FLOAT, false, vertexSize, 12);
+		GLES20.glVertexAttribPointer(texCoordIndex, 2, GLES20.GL_FLOAT, false, vertexSize, 24);
 		GLES20.glVertexAttribPointer(boneIndicesIndex, 4, GLES20.GL_UNSIGNED_BYTE, false, vertexSize, 32);
 		GLES20.glVertexAttribPointer(boneWeightsIndex, 3, GLES20.GL_FLOAT, false, vertexSize, 36);
 		//data.position(triangleOffset);
@@ -292,6 +293,7 @@ public class AnimatedMesh {
 		
 		GLES20.glDisableVertexAttribArray(positionIndex);
 		GLES20.glDisableVertexAttribArray(normalIndex);
+		GLES20.glDisableVertexAttribArray(texCoordIndex);
 		GLES20.glDisableVertexAttribArray(boneIndicesIndex);
 		GLES20.glDisableVertexAttribArray(boneWeightsIndex);
 	}

+ 110 - 48
src/de/tudarmstadt/informatik/hostage/ui2/fragment/opengl/ThreatIndicatorGLRenderer.java

@@ -2,36 +2,26 @@ package de.tudarmstadt.informatik.hostage.ui2.fragment.opengl;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
 import java.util.Scanner;
 
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 import android.content.res.AssetManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView.Renderer;
+import android.opengl.GLUtils;
 import android.opengl.Matrix;
 import android.util.Log;
 
 public class ThreatIndicatorGLRenderer implements Renderer {
-	public static int loadShader(int type, String source) {
-		int shader = GLES20.glCreateShader(type);
-		GLES20.glShaderSource(shader, source);
-		GLES20.glCompileShader(shader);
-		Log.i("gl", GLES20.glGetShaderInfoLog(shader));
-		return shader;
-	}
+	private static int threatLevel = 0;
 	
-	public static int loadProgram(String vertexSource, String fragmentSource) {
-		int program = GLES20.glCreateProgram();
-		GLES20.glAttachShader(program, loadShader(GLES20.GL_VERTEX_SHADER, vertexSource));
-		GLES20.glAttachShader(program, loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource));
-		GLES20.glLinkProgram(program);
-		return program;
+	public static void setThreatLevel(int level) {
+		threatLevel = level;
 	}
 	
 	public static AssetManager assets;
@@ -41,37 +31,61 @@ public class ThreatIndicatorGLRenderer implements Renderer {
 	private float aspectRatio;
 	
 	private int program;
-	private FloatBuffer vertexBuffer;
 	private float [] modelview;
 	private float [] projection;
 	private float [] mvp;
 	
 	private AnimatedMesh androidMesh = null;
+	private AnimatedMesh beeMesh = null;
+	private int androidTexture;
+	private int beeTexture;
 
 	public ThreatIndicatorGLRenderer() {}
 	
+	public int loadTexture(String filePath) {
+		Bitmap bitmap = null;
+		try {
+			bitmap = BitmapFactory.decodeStream(assets.open(filePath));
+		} catch (IOException e) {
+			e.printStackTrace();
+			return 0;
+		}
+		
+		int[] names = {0};
+		GLES20.glGenTextures(1, names, 0);
+		int tex = names[0];
+		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex);
+
+		GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
+		GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
+		GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
+		bitmap.recycle(); // memory is now gpu -> free it
+		
+		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex);
+		
+		return tex;
+	}
+	
 	public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
 		GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 		GLES20.glEnable(GLES20.GL_DEPTH_TEST);
 		GLES20.glEnable(GLES20.GL_CULL_FACE);
+		GLES20.glEnable(GLES20.GL_TEXTURE_2D);
 		
 		try {
 			InputStream is = assets.open("meshes/android.amh");
 			androidMesh = new AnimatedMesh(is);
 		} catch (IOException e) {
-			Log.e("gl", "Couldn't open mesh");
+			Log.e("gl", "Couldn't open android mesh");
 		}
-
-		final float [] positions = {
-				0.0f, 0.5f, 0.0f, 1.0f,
-				0.5f, -0.5f, 0.0f, 1.0f,
-				-0.5f, -0.5f, 0.0f, 1.0f,
-		};
-		ByteBuffer bb = ByteBuffer.allocateDirect(4 * positions.length);
-		bb.order(ByteOrder.nativeOrder());
-		vertexBuffer = bb.asFloatBuffer();
-		vertexBuffer.put(positions);
-		vertexBuffer.position(0);
+		androidTexture = loadTexture("textures/android-tex.png");
+		try {
+			InputStream is = assets.open("meshes/bee.amh");
+			beeMesh = new AnimatedMesh(is);
+		} catch (IOException e) {
+			Log.e("gl", "Couldn't open bee mesh");
+		}
+		beeTexture = loadTexture("textures/bee-tex.png");
 		
 		modelview = new float[16];
 		Matrix.setIdentityM(modelview, 0);
@@ -91,42 +105,62 @@ public class ThreatIndicatorGLRenderer implements Renderer {
 		}
 		program = loadProgram(vertexSource, fragmentSource);
 	}
+
+	static float beeAnimation = 0.0f;
 	
-	// see http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string
-	private static String inputStreamToString(InputStream is) {
-	    Scanner scanner = new Scanner(is);
-		Scanner s = scanner.useDelimiter("\\A");
-	    String result = s.hasNext() ? s.next() : "";
-	    scanner.close();
-	    return result;
+	private float[] mixColor(float alpha, float[] color1, float[] color2) {
+		float[] color3 = new float[4];
+		color3[0] = (1.0f - alpha) * color1[0] + alpha * color2[0];
+		color3[1] = (1.0f - alpha) * color1[1] + alpha * color2[1];
+		color3[2] = (1.0f - alpha) * color1[2] + alpha * color2[2];
+		color3[3] = (1.0f - alpha) * color1[3] + alpha * color2[3];
+		return color3;
 	}
-
+	
 	public void onDrawFrame(GL10 arg0) {
 		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
 		
 		GLES20.glUseProgram(program);
 		int colorUniformLoc = GLES20.glGetUniformLocation(program, "color");
+		int textureUniformLoc = GLES20.glGetUniformLocation(program, "texture");
 		int mvpUniformLoc = GLES20.glGetUniformLocation(program, "mvp");
 		
-		float [] color = {0.6f, 1.0f, 0.0f, 1.0f};
+		//final float[] androidColor = {165.0f / 255.0f, 202.0f / 255.0f, 57.0f / 255.0f, 1.0f}; // ok
+		final float[] whiteColor = {1.0f, 1.0f, 1.0f, 1.0f};
+		final float[] redColor = {2.0f, 0.4f, 0.2f, 1.0f};
+		final float[] yellowColor = {1.0f, 1.0f, 0.0f, 1.0f};
+		
+		float[] color = mixColor(0.5f + 0.5f * (float)Math.sin(0.2f * beeAnimation), whiteColor, redColor);
 		GLES20.glUniform4fv(colorUniformLoc, 1, color, 0);
-		//Matrix.rotateM(mvp, 0, 4.0f, 0.0f, 0.0f, 1.0f);
+		Log.i("gl", color[0]+" "+color[1]+" "+color[2]+" "+color[3]);
+		
+		GLES20.glUniform1i(textureUniformLoc, 0);
+		
 		Matrix.setIdentityM(modelview, 0);
-		Matrix.translateM(modelview, 0, 0.0f, -0.5f, 0.0f);
-		Matrix.rotateM(modelview, 0, -90.0f, 1.0f, 0.0f, 0.0f);
+		Matrix.translateM(modelview, 0, 0.0f, -0.5f, -2.0f);
+		Matrix.rotateM(modelview, 0, -80.0f, 1.0f, 0.0f, 0.0f);
 		Matrix.multiplyMM(mvp, 0, projection, 0, modelview, 0);
 		
 		GLES20.glUniformMatrix4fv(mvpUniformLoc, 1, false, mvp, 0);
 		
-		/*
-		GLES20.glEnableVertexAttribArray(positionAttribLoc);
-		GLES20.glVertexAttribPointer(positionAttribLoc, 4, GLES20.GL_FLOAT, false, 0, vertexBuffer);
-		GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
-		GLES20.glDisableVertexAttribArray(positionAttribLoc);
-		 */
-		
+		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, androidTexture);
 		androidMesh.tick();
 		androidMesh.draw(program);
+		
+		GLES20.glUniform4fv(colorUniformLoc, 1, whiteColor, 0);
+
+		beeAnimation += 1.0f;
+		float beeSize = 0.2f;
+		Matrix.rotateM(modelview, 0, -4.0f * beeAnimation, 0.0f, 0.0f, 1.0f);
+		Matrix.translateM(modelview, 0, 0.6f, 0.0f, 0.7f + 0.1f * (float)Math.sin(0.2f * beeAnimation));
+		Matrix.rotateM(modelview, 0, 20.0f * (float)Math.cos(0.2f * beeAnimation), 1.0f, 0.0f, 0.0f);
+		Matrix.scaleM(modelview, 0, beeSize, beeSize, beeSize);
+		Matrix.multiplyMM(mvp, 0, projection, 0, modelview, 0);
+		GLES20.glUniformMatrix4fv(mvpUniformLoc, 1, false, mvp, 0);
+
+		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, beeTexture);
+		beeMesh.tick();
+		beeMesh.draw(program);
 	}
 
 	public void onSurfaceChanged(GL10 arg0, int w, int h) {
@@ -134,6 +168,34 @@ public class ThreatIndicatorGLRenderer implements Renderer {
 		height = h;
 		aspectRatio = (float)w / (float)h;
 		Matrix.orthoM(projection, 0, -aspectRatio, aspectRatio, -1.0f, 1.0f, -1.0f, 1.0f);
+		float near = 0.1f;
+		float fov = 2.0f;
+		Matrix.frustumM(projection, 0, near * -aspectRatio, near * aspectRatio, -near, near, fov * near, 100.0f);
 		GLES20.glViewport(0, 0, width, height);
 	}
+	
+	// see http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string
+	private static String inputStreamToString(InputStream is) {
+	    Scanner scanner = new Scanner(is);
+		Scanner s = scanner.useDelimiter("\\A");
+	    String result = s.hasNext() ? s.next() : "";
+	    scanner.close();
+	    return result;
+	}
+	
+	public static int loadShader(int type, String source) {
+		int shader = GLES20.glCreateShader(type);
+		GLES20.glShaderSource(shader, source);
+		GLES20.glCompileShader(shader);
+		Log.i("gl", GLES20.glGetShaderInfoLog(shader));
+		return shader;
+	}
+	
+	public static int loadProgram(String vertexSource, String fragmentSource) {
+		int program = GLES20.glCreateProgram();
+		GLES20.glAttachShader(program, loadShader(GLES20.GL_VERTEX_SHADER, vertexSource));
+		GLES20.glAttachShader(program, loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource));
+		GLES20.glLinkProgram(program);
+		return program;
+	}
 }