Android Open Source - Schooner-3D Sch3 D






From Project

Back to project page Schooner-3D.

License

The source code is released under:

Apache License

If you think the Android project Schooner-3D listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2012 Dan Mercer//from  w w  w .j  a v a2  s  .  c o m
 * 
 * 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 com.supermercerbros.gameengine.parsers;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;

import android.util.Log;
import android.util.SparseArray;

import com.supermercerbros.gameengine.armature.Action;
import com.supermercerbros.gameengine.armature.Bone;
import com.supermercerbros.gameengine.armature.Skeleton;
import com.supermercerbros.gameengine.math.BezierCurve;
import com.supermercerbros.gameengine.math.Curve;
import com.supermercerbros.gameengine.motion.CurveMovement;
import com.supermercerbros.gameengine.util.BetterDataInputStream;
import com.supermercerbros.gameengine.util.Utils;

/**
 * Contains parsers for the Schooner 3D file formats (sch3Dmesh,
 * sch3Dmovements, sch3Darmature).
 */
public class Sch3D {
  private static final String TAG = Sch3D.class.getSimpleName();
  
  public static PreObjectData parseMesh(InputStream is)
      throws IOException {
    BetterDataInputStream data = new BetterDataInputStream(is);
    
    final int version = data.readInt();
    if (version == 1) {
      final byte flags = data.readByte();
      final boolean tris = Utils.checkBit(flags, 0);
      final boolean textured = Utils.checkBit(flags, 1);
      final boolean armatureIndexed = Utils.checkBit(flags, 2);
      
      final int faceCount = data.readShort() & 0x0000FFFF;
      final short vertCount = data.readShort();
      
      final short[] indices;
      if (tris) {
        indices = new short[faceCount * 3];
        data.readShortArray(indices, 0, faceCount * 3);
      } else {
        indices = new short[faceCount * 6];
        final short[] temp = new short[faceCount * 4];
        data.readShortArray(temp, 0, faceCount * 4);
        
        // Triangulate quads (split each face into two tris)
        for (int i = 0; i < faceCount; i++) {
          // For each quad, get its four indices
          final short a = temp[i * 4];
          final short b = temp[i * 4 + 1];
          final short c = temp[i * 4 + 2];
          final short d = temp[i * 4 + 3];
          
          // First half of quad
          indices[i * 6] = a;
          indices[i * 6 + 1] = b;
          indices[i * 6 + 2] = c;
          
          // Second half of quad
          indices[i * 6 + 3] = a;
          indices[i * 6 + 4] = c;
          indices[i * 6 + 5] = d;
        }
      }
      
      final float[] verts = new float[vertCount * 3];
      data.readFloatArray(verts, 0, vertCount * 3);
      
      final short[][] doubles;
      final float[] uvs;
      if (textured) {
        final short sharpCount = data.readShort();
        if (sharpCount > 0) {
          final short[] sharpVerts = new short[sharpCount];
          data.readShortArray(sharpVerts, 0, sharpCount);
          
          final LinkedList<Short> doublesList = new LinkedList<Short>();
          
          int sharpArrayIndex1 = 0;
          for (short v1 = 0; v1 < vertCount - 1; v1++) {
            if (sharpArrayIndex1 < sharpCount && sharpVerts[sharpArrayIndex1] == v1) {
              sharpArrayIndex1++;
              continue;
            }
            
            int sharpArrayIndex2 = sharpArrayIndex1;
            for (short v2 = (short) (v1 + 1); v2 < vertCount; v2++) {
              if (sharpArrayIndex2 < sharpCount && sharpVerts[sharpArrayIndex2] == v2) {
                sharpArrayIndex2++;
                continue;
              }
              
              final boolean coincident = 
                  verts[v1 * 3 + 0] == verts[v2 * 3 + 0] &&
                  verts[v1 * 3 + 1] == verts[v2 * 3 + 1] &&
                  verts[v1 * 3 + 2] == verts[v2 * 3 + 2];
              if (coincident) {
                doublesList.add(v1);
                doublesList.add(v2);
              }
            }
          }
          
          int pairCount = doublesList.size() / 2;
          doubles = new short[2][pairCount];
          for (int i = 0; i < pairCount; i++) {
            doubles[0][i] = doublesList.get(i * 2);
            doubles[1][i] = doublesList.get(i * 2 + 1);
          }
        } else {
          final LinkedList<Short> doublesList = new LinkedList<Short>();
          for (short v1 = 0; v1 < vertCount - 1; v1++) {
            for (short v2 = (short) (v1 + 1); v2 < vertCount; v2++) {
              final boolean coincident = 
                  verts[v1 * 3 + 0] == verts[v2 * 3 + 0] &&
                  verts[v1 * 3 + 1] == verts[v2 * 3 + 1] &&
                  verts[v1 * 3 + 2] == verts[v2 * 3 + 2];
              if (coincident) {
                doublesList.add(v1);
                doublesList.add(v2);
              }
            }
          }
          
          int pairCount = doublesList.size() / 2;
          doubles = new short[2][pairCount];
          for (int i = 0; i < pairCount; i++) {
            doubles[0][i] = doublesList.get(i * 2);
            doubles[1][i] = doublesList.get(i * 2 + 1);
          }
        }
        uvs = new float[vertCount * 2];
        data.readFloatArray(uvs, 0, vertCount * 2);
      } else {
        doubles = null;
        uvs = null;
      }
      
      final byte[][] boneIndices;
      final float[][] boneWeights;
      if (armatureIndexed) {
        boneIndices = new byte[vertCount][];
        boneWeights = new float[vertCount][];
        for (int i = 0; i < vertCount; i++) {
          final byte boneCount = data.readByte();
          boneIndices[i] = new byte[boneCount];
          boneWeights[i] = new float[boneCount];
          data.readByteArray(boneIndices[i], 0, boneCount);
          data.readFloatArray(boneWeights[i], 0, boneCount);
        }
      } else {
        boneIndices = null;
        boneWeights = null;
      }
      
      data.close();
      return new PreObjectData(verts, indices, uvs, doubles,
          boneIndices, boneWeights);
    } else {
      data.close();
      throw new IOException("File version is incorrect.");
    }
  }
  
  public static HashMap<String, CurveMovement> parseMovements(
      InputStream is) throws IOException {
    final BetterDataInputStream data = new BetterDataInputStream(is);
    final HashMap<String, CurveMovement> map = new HashMap<String, CurveMovement>();
    
    final int version = data.readInt();
    if (version == 1) {
      while (data.hasNext()) {
        String name = data.readString();
        CurveMovement movement = readMovement(data);
        map.put(name, movement);
      }
      data.close();
      return map;
    } else {
      data.close();
      throw new IOException("File version is incorrect.");
    }
  }

  public static Skeleton parseSkeleton(GameFactory gf, InputStream is, String id) throws IOException {
    final BetterDataInputStream data = new BetterDataInputStream(is);
    final int version = data.readInt();
    if (version == 1) {
      
      // Parse Skeleton
      final short boneCount = (short) (((short) data.readByteDebug()) + 1);
      ArrayList<PreBoneData> preBones = new ArrayList<PreBoneData>();
      for (byte i = 0; i < boneCount; i++) {
        final float x = data.readFloatDebug(),
            y = data.readFloatDebug(),
            z = data.readFloatDebug();
        preBones.add(new PreBoneData(i, x, y, z, 
            (byte) (data.readByteDebug() - 1)));
      }
      
      // connect parents to children
      for (PreBoneData preBone : preBones) {
        final byte parentIndex = preBone.parentIndex;
        if (parentIndex != -1) {
          preBones.get(parentIndex).addChild(preBone);
        }
      }
      
      // convert PreBoneDatas to Bones
      final LinkedList<Bone> roots = new LinkedList<Bone>();
      for (PreBoneData preBone : preBones) {
        if (preBone.isRoot()) {
          roots.add(preBone.toBone());
        }
      }
      // Construct skeleton
      final Skeleton skeleton = new Skeleton(id, roots);
      
      // Parse Actions
      final HashMap<String, Action> actions = new HashMap<String, Action>();
      while (data.hasNext()) {
        final String name = data.readString();
        Log.d(TAG, "NAME: " + name);
        
        CurveMovement movement = readMovement(data);
        
        // Parse Action
        SparseArray<Curve> curves = new SparseArray<Curve>();
        for (byte i = 0; i < boneCount; i++) {
          // For each bone
          final int offset = i * 4;
          
          for(int j = 0; j < 4; j++) {
            // For each curve
            final int pointCount = (data.readByteDebug() & 0x00FF) * 3 - 2;
            
            if (pointCount > 0) { // If the curve has keyframes
              final float[] frames = new float[pointCount], values = new float[pointCount];
              for (int index = 0; index < pointCount; index++) {
                frames[index] = data.readFloatDebug();
                values[index] = data.readFloatDebug();
              }
              curves.append(offset + j, new BezierCurve(frames, values));
            }
          }
        }
        actions.put(name, new Action(movement, curves));
      }
      data.close();
      gf.setActions(actions);
      return skeleton;
    } else {
      data.close();
      throw new IOException("File version is incorrect.");
    }
  }

  /**
   * @param data
   * @return
   * @throws IOException
   */
  private static CurveMovement readMovement(final BetterDataInputStream data)
      throws IOException {
    CurveMovement movement;
    final byte flagsByte = data.readByteDebug();
    
    // Parse Movement
    if (flagsByte != 0) { // If Movement exists for this Action...
      boolean[] flags = Utils.checkBits(flagsByte, 4);
      Log.d(TAG, "FLAGS: " + Arrays.toString(flags));
      
      int curveCount = 0;
      final boolean moveLoc = flags[0];
      final boolean moveRot = flags[1];
      final boolean moveScale = flags[2];
      final boolean moveScaleAxis = flags[3];
      if (moveLoc) {
        curveCount += 3;
      }
      if (moveRot) {
        curveCount += 4;
      }
      if (moveScale) {
        curveCount += 1;
      } else if (moveScaleAxis) {
        curveCount += 3;
      }
      Log.d(TAG, "CURVE COUNT: " + curveCount);
      
      Curve[] curves = new Curve[curveCount];
      int curveIndex = 0;
      // Parse location curves
      if (moveLoc) {
        final int pointCount = (data.readByteDebug() & 0xFFFF) * 3 - 2;
        if (pointCount > 0) {
          Log.d(TAG, "Location curves have "+ pointCount + " points.");
          for (int i = 0; i < 3; i++) { 
            float[] frames = new float[pointCount];
            float[] values = new float[pointCount];
            
            for (int pointIndex = 0; pointIndex < pointCount; pointIndex++) {
              frames[pointIndex] = data.readFloatDebug();
              values[pointIndex] = data.readFloatDebug();
            }
            curves[curveIndex + i] = new BezierCurve(frames, values);
          }
        } else {
          curves[curveIndex] = null;
          curves[curveIndex + 1] = null;
          curves[curveIndex + 2] = null;
          Log.d(TAG, "Location curves have 0 points.");
        }
        curveIndex += 3;
      }
      // Parse rotation curves
      if (moveRot) {
        final int pointCount = (data.readByteDebug() & 0xFFFF)* 3 - 2;
        if (pointCount > 0) {
          Log.d(TAG, "Rotation curves have "+ pointCount + " points.");
          for (int i = 0; i < 4; i++) { 
            float[] frames = new float[pointCount];
            float[] values = new float[pointCount];
            
            for (int pointIndex = 0; pointIndex < pointCount; pointIndex++) {
              frames[pointIndex] = data.readFloatDebug();
              values[pointIndex] = data.readFloatDebug();
              Log.d(TAG, "(" + frames[pointIndex] + ", " + values[pointIndex] + ")");
            }
            
            curves[curveIndex + i] = new BezierCurve(frames, values);
          }
        } else {
          curves[curveIndex] = null;
          curves[curveIndex + 1] = null;
          curves[curveIndex + 2] = null;
          curves[curveIndex + 3] = null;
          Log.d(TAG, "Rotation curves have 0 points.");
        }
        curveIndex += 4;
      }
      // Parse scale curves
      if (moveScale) {
        // Uniform scale (1 curve)
        final int pointCount = (data.readByteDebug() & 0xFFFF) * 3 - 2;
        if (pointCount > 0) {
          Log.d(TAG, "Scale curve (uniform) has "+ pointCount + " points.");
          float[] frames = new float[pointCount];
          float[] values = new float[pointCount];

          for (int pointIndex = 0; pointIndex < pointCount; pointIndex++) {
            frames[pointIndex] = data.readFloatDebug();
            values[pointIndex] = data.readFloatDebug();
            Log.d(TAG, "(" + frames[pointIndex] + ", " + values[pointIndex] + ")");
          }

          curves[curveIndex] = new BezierCurve(frames, values);
        } else {
          curves[curveIndex] = null;
          Log.d(TAG, "Scale curve (uniform) has 0 points.");
        }
        //curveIndex += 1; Don't need to increment after last curve
      } else if (moveScaleAxis) {
        // Per-axis scale (3 curves)
        final int pointCount = (data.readByteDebug() & 0xFFFF) * 3 - 2;
        if (pointCount > 0) {
          Log.d(TAG, "Scale curves (per-axis) have "+ pointCount + " points.");
          for (int i = 0; i < 3; i++) {
            float[] frames = new float[pointCount];
            float[] values = new float[pointCount];
            
            for (int pointIndex = 0; pointIndex < pointCount; pointIndex++) {
              frames[pointIndex] = data.readFloatDebug();
              values[pointIndex] = data.readFloatDebug();
              Log.d(TAG, "(" + frames[pointIndex] + ", " + values[pointIndex] + ")");
            }
            
            curves[curveIndex + i] = new BezierCurve(frames, values);
          }
        } else {
          curves[curveIndex] = null;
          curves[curveIndex + 1] = null;
          curves[curveIndex + 2] = null;
          Log.d(TAG, "Scale curves (per-axis) have 0 points.");
        }
        //curveIndex += 3; Don't need to increment after last curves
      }
      
      movement = new CurveMovement(flagsByte, curves);
    } else {
      Log.d(TAG, "No movement curves.");
      movement = null;
    }
    return movement;
  }
}




Java Source Code List

com.supermercerbros.gameengine.GameActivity.java
com.supermercerbros.gameengine.GameView.java
com.supermercerbros.gameengine.Schooner3D.java
com.supermercerbros.gameengine.TestActivity.java
com.supermercerbros.gameengine.TestMaterials.java
com.supermercerbros.gameengine.TestObjects.java
com.supermercerbros.gameengine.animation.AnimationData.java
com.supermercerbros.gameengine.animation.Keyframe.java
com.supermercerbros.gameengine.animation.MeshAnimation.java
com.supermercerbros.gameengine.armature.ActionData.java
com.supermercerbros.gameengine.armature.Action.java
com.supermercerbros.gameengine.armature.BinarySkeletalVertexModifier.java
com.supermercerbros.gameengine.armature.Bone.java
com.supermercerbros.gameengine.armature.SkeletalVertexModifier.java
com.supermercerbros.gameengine.armature.Skeleton.java
com.supermercerbros.gameengine.collision.Bounds.java
com.supermercerbros.gameengine.collision.Collider.java
com.supermercerbros.gameengine.collision.CollisionDetector.java
com.supermercerbros.gameengine.collision.Collision.java
com.supermercerbros.gameengine.collision.DebugListener.java
com.supermercerbros.gameengine.collision.Edge.java
com.supermercerbros.gameengine.collision.Face.java
com.supermercerbros.gameengine.collision.Feature.java
com.supermercerbros.gameengine.collision.Intersection.java
com.supermercerbros.gameengine.collision.Line.java
com.supermercerbros.gameengine.collision.LocalDistMinimum.java
com.supermercerbros.gameengine.collision.Matrix.java
com.supermercerbros.gameengine.collision.OnCollisionCheckFinishedListener.java
com.supermercerbros.gameengine.collision.Plane.java
com.supermercerbros.gameengine.collision.Point.java
com.supermercerbros.gameengine.collision.Polyhedron.java
com.supermercerbros.gameengine.collision.SphereBounds.java
com.supermercerbros.gameengine.collision.Vector.java
com.supermercerbros.gameengine.collision.Vertex.java
com.supermercerbros.gameengine.debug.JankCatcher.java
com.supermercerbros.gameengine.debug.LoopLog.java
com.supermercerbros.gameengine.engine.Camera.java
com.supermercerbros.gameengine.engine.DataPipe.java
com.supermercerbros.gameengine.engine.EGLContextLostHandler.java
com.supermercerbros.gameengine.engine.Engine.java
com.supermercerbros.gameengine.engine.GameRenderer.java
com.supermercerbros.gameengine.engine.Light.java
com.supermercerbros.gameengine.engine.Normals.java
com.supermercerbros.gameengine.engine.RenderData.java
com.supermercerbros.gameengine.engine.Scene.java
com.supermercerbros.gameengine.engine.Time.java
com.supermercerbros.gameengine.engine.shaders.Material.java
com.supermercerbros.gameengine.engine.shaders.Program.java
com.supermercerbros.gameengine.engine.shaders.ShaderLib.java
com.supermercerbros.gameengine.engine.shaders.Shader.java
com.supermercerbros.gameengine.engine.shaders.VertexModifier.java
com.supermercerbros.gameengine.handlers.OnAnimationCompleteDispatcher.java
com.supermercerbros.gameengine.handlers.OnAnimationCompleteListener.java
com.supermercerbros.gameengine.hud.CoordsConverter.java
com.supermercerbros.gameengine.hud.GameHud.java
com.supermercerbros.gameengine.hud.HudElement.java
com.supermercerbros.gameengine.material.CelShadedMaterial.java
com.supermercerbros.gameengine.material.TexturedMaterial.java
com.supermercerbros.gameengine.math.BezierCurve.java
com.supermercerbros.gameengine.math.Curve.java
com.supermercerbros.gameengine.math.MatrixUtils.java
com.supermercerbros.gameengine.math.Quaternion.java
com.supermercerbros.gameengine.motion.CurveMovement.java
com.supermercerbros.gameengine.motion.MovementData.java
com.supermercerbros.gameengine.motion.Movement.java
com.supermercerbros.gameengine.objects.AnimatedMeshObject.java
com.supermercerbros.gameengine.objects.BasicMaterial.java
com.supermercerbros.gameengine.objects.BonedObject.java
com.supermercerbros.gameengine.objects.GameObject.java
com.supermercerbros.gameengine.objects.Metadata.java
com.supermercerbros.gameengine.parsers.ConstantCurve.java
com.supermercerbros.gameengine.parsers.GameFactory.java
com.supermercerbros.gameengine.parsers.PreBoneData.java
com.supermercerbros.gameengine.parsers.PreObjectData.java
com.supermercerbros.gameengine.parsers.Sch3D.java
com.supermercerbros.gameengine.render.Compositor.java
com.supermercerbros.gameengine.shaders.ProgramSource.java
com.supermercerbros.gameengine.texture.BitmapTexture.java
com.supermercerbros.gameengine.texture.ETC1CompressedTexture.java
com.supermercerbros.gameengine.texture.Texture.java
com.supermercerbros.gameengine.util.BetterDataInputStream.java
com.supermercerbros.gameengine.util.DelayedRunnable.java
com.supermercerbros.gameengine.util.GLES2.java
com.supermercerbros.gameengine.util.IPO.java
com.supermercerbros.gameengine.util.LoopingThread.java
com.supermercerbros.gameengine.util.Toggle.java
com.supermercerbros.gameengine.util.Utils.java