private BufferedInputStream file; private byte[] bytes = new byte[8]; private long filePos = 0; ... private void Skip(long count) throws IOException { file.skip(count); filePos += count; } private void Seek(long end) throws IOException { if (filePos < end) { Skip(end - filePos); filePos = end; } } private byte ReadByte() throws IOException { file.read(bytes, 0, 1); filePos++; return bytes[0]; } private int ReadUnsignedByte() throws IOException { file.read(bytes, 0, 1); filePos++; return (bytes[0]&0xff); } private int ReadUnsignedShort() throws IOException { file.read(bytes, 0, 2); filePos += 2; return ((bytes[1]&0xff) << 8 | (bytes[0]&0xff)); } private int ReadInt() throws IOException { file.read(bytes, 0, 4); filePos += 4; return (bytes[3]) << 24 | (bytes[2]&0xff) << 16 | (bytes[1]&0xff) << 8 | (bytes[0]&0xff); } private float ReadFloat() throws IOException { return Float.intBitsToFloat(ReadInt()); }
private Scene3D ProcessFile(long fileLen) throws IOException { Scene3D scene = null; while (filePos < fileLen) { int chunkID = ReadUnsignedShort(); int chunkLen = ReadInt() - 6; switch (chunkID) { case CHUNK_MAIN: if (scene == null) scene = ChunkMain(chunkLen); else Skip(chunkLen); break; default: Skip(chunkLen); } } return scene; } private Scene3D ChunkMain(int len) throws IOException { Scene3D scene = new Scene3D(); scene.materials = new ArrayList<Material3D>(); scene.objects = new ArrayList<Object3D>(); scene.lights = new ArrayList<Light3D>(); scene.animations = new ArrayList<Animation>(); long end = filePos + len; while (filePos < end) { int chunkID = ReadUnsignedShort(); int chunkLen = ReadInt() - 6; switch (chunkID) { case CHUNK_OBJMESH: Chunk3DEditor(scene, chunkLen); break; case CHUNK_KEYFRAMER: ChunkKeyframer(scene, chunkLen); break; case CHUNK_BACKCOL: scene.background = new float[4]; ChunkColor(chunkLen, scene.background); break; case CHUNK_AMB: scene.ambient = new float[4]; ChunkColor(chunkLen, scene.ambient); break; default: Skip(chunkLen); } } Seek(end); scene.Compute(0); return scene; }
GLES20.glVertexAttribPointer(maPosition, 3, GLES20.GL_FLOAT, false, 32, 0); GLES20.glVertexAttribPointer(maNormal, 3, GLES20.GL_FLOAT, false, 32, 12);
private void ChunkVector(float[] vec, int offset) throws IOException { vec[offset + 0] = ReadFloat(); vec[offset + 2] = ReadFloat(); vec[offset + 1] = ReadFloat(); }
mAmbient[0] = 0.587f; mAmbient[1] = 0.587f; mAmbient[2] = 0.587f; mAmbient[3] = 1.0f; mDiffuse[0] = 0.587f; mDiffuse[1] = 0.587f; mDiffuse[2] = 0.587f; mDiffuse[3] = 1.0f; mSpecular[0] = 0.896f; mSpecular[1] = 0.896f; mSpecular[2] = 0.896f; mSpecular[3] = 1.0f; ... int mats = obj.faceMats.size(); for (j = 0; j < mats; j++) { FaceMat mat = obj.faceMats.get(j); if (mat.material != null) { if (mat.material.ambient != null && scene.ambient != null) { for (k = 0; k < 3; k++) mAmbient[k] = mat.material.ambient[k] * scene.ambient[k]; GLES20.glUniform4fv(muAmbient, 1, mAmbient, 0); } else GLES20.glUniform4f(muAmbient, 0, 0, 0, 1); if (mat.material.diffuse != null) GLES20.glUniform4fv(muDiffuse, 1, mat.material.diffuse, 0); else GLES20.glUniform4fv(muDiffuse, 1, mDiffuse, 0); if (mat.material.specular != null) GLES20.glUniform4fv(muSpecular, 1, mat.material.specular, 0); else GLES20.glUniform4fv(muSpecular, 1, mSpecular, 0); GLES20.glUniform1f(muShininess, mat.material.shininess); } else { GLES20.glUniform4f(muAmbient, 0, 0, 0, 1); GLES20.glUniform4fv(muDiffuse, 1, mDiffuse, 0); GLES20.glUniform4fv(muSpecular, 1, mSpecular, 0); GLES20.glUniform1f(muShininess, 0); } GLES20.glDrawElements(GLES20.GL_TRIANGLES, mat.indexBuffer.length, GLES20.GL_UNSIGNED_SHORT, mat.bufOffset * 2); }
private final String vertexShaderCode = "precision mediump float;\n" + "uniform mat4 uMVPMatrix;\n" + "uniform mat4 uMVMatrix;\n" + "uniform mat3 uNMatrix;\n" + "uniform vec4 uAmbient;\n" + "uniform vec4 uDiffuse;\n" + "uniform vec4 uSpecular;\n" + "uniform float uShininess;\n" + ... "vec4 light_point_view_local(vec3 epos, vec3 normal, int idx) {\n" + " vec3 vert2light = uLight[idx].position - epos;\n" + " vec3 ldir = normalize(vert2light);\n" + " vec3 vdir = vec3(0.0, 0.0, 1.0);\n" + " vec3 halfv = normalize(ldir + vdir);\n" + " float NdotL = dot(normal, ldir);\n" + " float NdotH = dot(normal, halfv);\n" + " vec4 outCol = vec4(0.0, 0.0, 0.0, 1.0);\n" + " if (NdotL > 0.0) {\n" + " outCol = uLight[idx].color * uDiffuse * NdotL;\n" + " if (NdotH > 0.0 && uShininess > 0) {\n" + " outCol += uSpecular * pow(NdotH, uShininess);\n" + " }\n" + " }\n" + " return outCol;\n" + "}\n";
result = parent.result * move * rotate * scale; world = result * Move(-pivot) * trmatrix;
private void lerp3(float[] out, float[] from, float[] to, float t) { for (int i = 0; i < 3; i++) out[i] = from[i] + (to[i] - from[i]) * t; } private AnimKey findVec(AnimKey[] keys, float time) { AnimKey key = keys[keys.length - 1]; // We'll use either first, or last, or interpolated key for (int j = 0; j < keys.length; j++) { if (keys[j].time >= time) { if (j > 0) { float local = (time - keys[j - 1].time) / (keys[j].time - keys[j - 1].time); key = new AnimKey(); key.time = time; key.data = new float[3]; lerp3(key.data, keys[j - 1].data, keys[j].data, local); } else key = keys[j]; break; } } return key; } private void applyRot(float[] result, float[] data, float t) { if (Math.abs(data[3]) > 1.0e-7 && Math.hypot(Math.hypot(data[0], data[1]), data[2]) > 1.0e-7) Matrix.rotateM(result, 0, (float) (data[3] * t * 180 / Math.PI), data[0], data[1], data[2]); } public void Compute(float time) { int i, n = animations.size(); for (i = 0; i < n; i++) { Animation anim = animations.get(i); Object3D obj = anim.object; float[] result = new float[16]; Matrix.setIdentityM(result, 0); if (anim.position != null && anim.position.length > 0) { AnimKey key = findVec(anim.position, time); float[] pos = key.data; Matrix.translateM(result, 0, pos[0], pos[1], pos[2]); } if (anim.rotation != null && anim.rotation.length > 0) { // All rotations that are prior to the target time should be applied sequentially for (int j = anim.rotation.length - 1; j > 0; j--) { if (time >= anim.rotation[j].time) // rotation in the past, apply as is applyRot(result, anim.rotation[j].data, 1); else if (time > anim.rotation[j - 1].time) { // rotation between key frames, apply part of it float local = (time - anim.rotation[j - 1].time) / (anim.rotation[j].time - anim.rotation[j - 1].time); applyRot(result, anim.rotation[j].data, local); } // otherwise, it's a rotation in the future, skip it } // Always apply the first rotation applyRot(result, anim.rotation[0].data, 1); } if (anim.scaling != null && anim.scaling.length > 0) { AnimKey key = findVec(anim.scaling, time); float[] scale = key.data; Matrix.scaleM(result, 0, scale[0], scale[1], scale[2]); } if (anim.parent != null) Matrix.multiplyMM(anim.result, 0, anim.parent.result, 0, result, 0); else Matrix.translateM(anim.result, 0, result, 0, 0, 0, 0); if (obj != null && obj.trMatrix != null) { float[] pivot = new float[16]; Matrix.setIdentityM(pivot, 0); Matrix.translateM(pivot, 0, -anim.pivot[0], -anim.pivot[1], -anim.pivot[2]); Matrix.multiplyMM(result, 0, pivot, 0, obj.trMatrix, 0); } else { Matrix.setIdentityM(result, 0); Matrix.translateM(result, 0, -anim.pivot[0], -anim.pivot[1], -anim.pivot[2]); } Matrix.multiplyMM(anim.world, 0, anim.result, 0, result, 0); } }
num = scene.animations.size(); for (i = 0; i < num; i++) { Animation anim = scene.animations.get(i); Object3D obj = anim.object; if (obj == null) continue; Matrix.multiplyMM(mMVMatrix, 0, mVMatrix, 0, anim.world, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVMatrix, 0); // Apply a ModelView Projection transformation GLES20.glUniformMatrix4fv(muMVPMatrix, 1, false, mMVPMatrix, 0); GLES20.glUniformMatrix4fv(muMVMatrix, 1, false, mMVMatrix, 0); for (j = 0; j < 3; j++) for (k = 0; k < 3; k++) mNMatrix[k*3 + j] = mMVMatrix[k*4 + j]; GLES20.glUniformMatrix3fv(muNMatrix, 1, false, mNMatrix, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, obj.glVertices); GLES20.glVertexAttribPointer(maPosition, 3, GLES20.GL_FLOAT, false, 32, 0); GLES20.glVertexAttribPointer(maNormal, 3, GLES20.GL_FLOAT, false, 32, 12); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); ...
Source: https://habr.com/ru/post/144955/
All Articles