protected void initScene() {
   RajLog.systemInformation();
   setFrameRate(60);
   LoaderGCode gCodeParser =
       new LoaderGCode(
           getResources(), getTextureManager(), R.raw.calibrationcube_404020_psm_pla35);
   try {
     Object3D gCode3D = gCodeParser.parse().getParsedObject();
     if (null != gCode3D) {
       Line3D firstPos = (Line3D) gCode3D.getChildAt(0);
       Line3D lastPos = null;
       if (gCode3D.getNumChildren() < 2) {
         lastPos = firstPos;
       } else {
         lastPos = (Line3D) gCode3D.getChildAt(gCode3D.getNumChildren() - 1);
       }
       getCurrentCamera().setPosition(0, 0, lastPos.getPoint(0).z + 150);
       getCurrentCamera().setLookAt(0, 0, 0);
       float scaleFactor = 0.7f;
       gCode3D.setScale(scaleFactor);
       gCode3D.setPosition(
           -firstPos.getPoint(0).x * scaleFactor, -firstPos.getPoint(0).y * scaleFactor, 0);
       gCode3D.setRotation(360 - 35, 0, 360 - 15);
       Material mat = new Material();
       for (int i = 0; i < gCode3D.getNumChildren(); i++) {
         gCode3D.getChildAt(i).setMaterial(mat);
       }
       addChild(gCode3D);
     }
   } catch (Exception e) {
     RajLog.e(
         new StringBuilder()
             .append("error init'ing gcode GL scene:\n")
             .append(Log.getStackTraceString(e))
             .toString());
   }
 }
Exemple #2
0
  private void setMeshTextures(Object3D o, String name) throws TextureException, ParsingException {
    Stack<FBXValues.Objects.Texture> textures = mFbx.objects.textures;
    Stack<Connect> connections = mFbx.connections.connections;
    int numTex = textures.size();
    int numCon = connections.size();

    for (int i = 0; i < numTex; ++i) {
      FBXValues.Objects.Texture tex = textures.get(i);
      for (int j = 0; j < numCon; ++j) {
        Connect conn = connections.get(j);

        if (conn.object2.equals(name) && conn.object1.equals(tex.textureName)) {
          // -- one texture for now
          String textureName = tex.fileName;

          Bitmap bitmap = null;

          switch (getType()) {
            case ASSETS:
              try {
                String filePath =
                    getParentFolder() + File.separatorChar + getOnlyFileName(textureName);
                bitmap = BitmapFactory.decodeStream(getAssets().open(filePath));
              } catch (Exception e) {
                throw new ParsingException(
                    "["
                        + getClass().getCanonicalName()
                        + "] Could not find file "
                        + getOnlyFileName(textureName));
              }
              break;
            case RAW:
              int identifier =
                  getResources()
                      .getIdentifier(
                          getFileNameWithoutExtension(textureName).toLowerCase(Locale.getDefault()),
                          "drawable",
                          getResources().getResourcePackageName(getResourceId()));
              bitmap = BitmapFactory.decodeResource(getResources(), identifier);
              break;
            case SDCARD:
              try {
                String filePath =
                    getParentFolder() + File.separatorChar + getOnlyFileName(textureName);
                bitmap = BitmapFactory.decodeFile(filePath);
              } catch (Exception e) {
                throw new ParsingException(
                    "["
                        + getClass().getCanonicalName()
                        + "] Could not find file "
                        + getOnlyFileName(textureName));
              }
              break;
          }
          o.getMaterial().setColorInfluence(0);
          o.getMaterial().addTexture(new Texture(textureName.replaceAll("[\\W]|_", ""), bitmap));
          return;
        }
      }
    }
  }
Exemple #3
0
  private void buildMesh(Model model, Stack<ALight> lights)
      throws TextureException, ParsingException {
    Object3D o = new Object3D(model.name);
    boolean hasUVs = model.layerElementUV.uVIndex != null;

    int[] vidx = model.polygonVertexIndex.data;
    int[] uvidx = null;
    float[] modelVerts = model.vertices.data;
    float[] modelNorm = model.layerElementNormal.normals.data;
    float[] modelUv = null;

    ArrayList<Integer> indices = new ArrayList<Integer>();
    ArrayList<Float> vertices = new ArrayList<Float>();
    ArrayList<Float> normals = new ArrayList<Float>();
    ArrayList<Float> uvs = null;

    if (hasUVs) {
      uvs = new ArrayList<Float>();
      uvidx = model.layerElementUV.uVIndex.data;
      modelUv = model.layerElementUV.uV.data;
    }

    int count = 0;
    int indexCount = 0;
    int[] triIds = new int[3];
    int[] quadIds = new int[6];
    int i = 0, j = 0, k = 0;
    int vidxLen = vidx.length;

    for (i = 0; i < vidxLen; ++i) {
      count++;

      if (vidx[i] < 0) {
        if (count == 3) {
          int index1 = vidx[i - 2], index2 = vidx[i - 1], index3 = (vidx[i] * -1) - 1;

          indices.add(indexCount++);
          indices.add(indexCount++);
          indices.add(indexCount++);

          triIds[0] = index1 * 3;
          triIds[1] = index2 * 3;
          triIds[2] = index3 * 3;

          for (j = 0; j < 3; ++j) {
            int cid = triIds[j];
            for (k = 0; k < 3; ++k) {
              vertices.add(modelVerts[cid + k]);
              int dir = i == 0 ? -1 : 1;
              normals.add(modelNorm[cid + k] * dir);
            }
          }

          if (hasUVs) {
            int uvIndex3 = uvidx[i] * 2;
            int uvIndex2 = uvidx[i - 1] * 2;
            int uvIndex1 = uvidx[i - 2] * 2;

            uvs.add(modelUv[uvIndex1 + 0]);
            uvs.add(1f - modelUv[uvIndex1 + 1]);

            uvs.add(modelUv[uvIndex2 + 0]);
            uvs.add(1f - modelUv[uvIndex2 + 1]);

            uvs.add(modelUv[uvIndex3 + 0]);
            uvs.add(1f - modelUv[uvIndex3 + 1]);
          }
        } else {
          int index1 = vidx[i - 3];
          int index2 = vidx[i - 2];
          int index3 = vidx[i - 1];
          int index4 = (vidx[i] * -1) - 1;

          indices.add(indexCount++);
          indices.add(indexCount++);
          indices.add(indexCount++);
          indices.add(indexCount++);
          indices.add(indexCount++);
          indices.add(indexCount++);

          quadIds[0] = index1 * 3;
          quadIds[1] = index2 * 3;
          quadIds[2] = index3 * 3;
          quadIds[3] = index4 * 3;
          quadIds[4] = index1 * 3;
          quadIds[5] = index3 * 3;

          for (j = 0; j < 6; ++j) {
            int cid = quadIds[j];
            for (k = 0; k < 3; ++k) {
              vertices.add(modelVerts[cid + k]);
              normals.add(modelNorm[cid + k]);
            }
          }

          if (hasUVs) {
            int uvIndex1 = uvidx[i - 3] * 2;
            int uvIndex2 = uvidx[i - 2] * 2;
            int uvIndex3 = uvidx[i - 1] * 2;
            int uvIndex4 = uvidx[i] * 2;

            quadIds[0] = uvIndex1;
            quadIds[1] = uvIndex2;
            quadIds[2] = uvIndex3;
            quadIds[3] = uvIndex4;
            quadIds[4] = uvIndex1;
            quadIds[5] = uvIndex3;

            for (j = 0; j < 6; ++j) {
              int cid = quadIds[j];
              for (k = 0; k < 2; ++k) {
                if (k == 0) uvs.add(modelUv[cid + k]);
                else uvs.add(1f - modelUv[cid + k]);
              }
            }
          }
        }
        count = 0;
      }
    }

    o.setData(
        convertFloats(vertices),
        convertFloats(normals),
        hasUVs ? convertFloats(uvs) : null,
        null,
        convertIntegers(indices));

    vertices.clear();
    vertices = null;
    normals.clear();
    normals = null;
    if (hasUVs) {
      uvs.clear();
      uvs = null;
    }
    indices.clear();
    indices = null;
    o.setMaterial(getMaterialForMesh(o, model.name));
    setMeshTextures(o, model.name);

    o.setPosition(model.properties.lclTranslation);
    o.setX(o.getX() * -1);
    o.setScale(model.properties.lclScaling);
    o.setRotation(model.properties.lclRotation);
    o.setRotZ(-o.getRotZ());

    mRootObject.addChild(o);
  }
    protected void initScene() {
      PointLight light = new PointLight();
      light.setZ(6);
      light.setPower(2);

      getCurrentScene().addLight(light);

      Texture jetTexture = new Texture("jetTexture", R.drawable.jettexture);
      SphereMapTexture sphereMapTexture =
          new SphereMapTexture("manilaSphereMapTex", R.drawable.manila_sphere_map);

      jetTexture.setInfluence(.8f);
      // -- important!
      sphereMapTexture.isEnvironmentTexture(true);
      sphereMapTexture.setInfluence(.2f);

      Object3D jet1 = null;
      // -- sphere map with texture

      try {
        Material material1 = new Material();
        material1.enableLighting(true);
        material1.setDiffuseMethod(new DiffuseMethod.Lambert());
        material1.addTexture(jetTexture);
        material1.addTexture(sphereMapTexture);

        ObjectInputStream ois;
        ois = new ObjectInputStream(mContext.getResources().openRawResource(R.raw.jet));
        jet1 = new Object3D((SerializedObject3D) ois.readObject());
        jet1.setMaterial(material1);
        jet1.setY(2.5f);
        addChild(jet1);
      } catch (Exception e) {
        e.printStackTrace();
      }

      Vector3 axis = new Vector3(2, -4, 1);
      axis.normalize();

      Animation3D anim1 = new RotateAnimation3D(axis, 360);
      anim1.setRepeatMode(RepeatMode.INFINITE);
      anim1.setDuration(12000);
      anim1.setTransformable3D(jet1);
      registerAnimation(anim1);
      anim1.play();

      sphereMapTexture = new SphereMapTexture("manilaSphereMapTex2", R.drawable.manila_sphere_map);
      sphereMapTexture.isEnvironmentTexture(true);
      sphereMapTexture.setInfluence(.5f);

      Material material2 = new Material();
      // -- important, indicate that we want to mix the sphere map with a color
      material2.enableLighting(true);
      material2.setDiffuseMethod(new DiffuseMethod.Lambert());
      try {
        material2.addTexture(sphereMapTexture);
      } catch (TextureException e) {
        e.printStackTrace();
      }
      material2.setColorInfluence(.5f);

      Object3D jet2 = jet1.clone(false);
      jet2.setMaterial(material2);
      // -- also specify a color
      jet2.setColor(0xff666666);
      jet2.setY(-2.5f);
      addChild(jet2);

      Animation3D anim2 = new RotateAnimation3D(axis, -360);
      anim2.setRepeatMode(RepeatMode.INFINITE);
      anim2.setDuration(12000);
      anim2.setTransformable3D(jet2);
      registerAnimation(anim2);
      anim2.play();

      getCurrentCamera().setPosition(0, 0, 14);
    }
    public void setMaterial(Object3D object, String materialName) throws TextureException {
      MaterialDef matDef = null;

      for (int i = 0; i < mMaterials.size(); ++i) {
        if (mMaterials.get(i).name.equals(materialName)) {
          matDef = mMaterials.get(i);
          break;
        }
      }

      boolean hasTexture = matDef != null && matDef.diffuseTexture != null;
      boolean hasBump = matDef != null && matDef.bumpTexture != null;
      boolean hasSpecularTexture = matDef != null && matDef.specularColorTexture != null;
      boolean hasSpecular =
          matDef != null && matDef.specularColor > 0xff000000 && matDef.specularCoefficient > 0;

      AMaterial mat = null;

      if (hasSpecular && !hasBump) mat = new PhongMaterial();
      else if (hasBump && !hasSpecularTexture) mat = new NormalMapMaterial();
      else if (hasBump && hasSpecularTexture) mat = new NormalMapPhongMaterial();
      else mat = new DiffuseMaterial();

      mat.setUseSingleColor(!hasTexture);
      object.setMaterial(mat);
      object.setColor(
          matDef != null ? matDef.diffuseColor : (0xff000000 + ((int) (Math.random() * 0xffffff))));
      if (hasSpecular || hasSpecularTexture) {
        PhongMaterial phong = (PhongMaterial) mat;
        phong.setSpecularColor(matDef.specularColor);
        phong.setShininess(matDef.specularCoefficient);
      }

      if (hasTexture) {
        RajLog.i("hastex " + object.getName() + ", " + matDef.diffuseTexture);
        if (mFile == null) {
          int identifier =
              mResources.getIdentifier(
                  getFileNameWithoutExtension(matDef.diffuseTexture), "drawable", mResourcePackage);
          mat.addTexture(new Texture(identifier));
        } else {
          String filePath =
              mFile.getParent() + File.separatorChar + getOnlyFileName(matDef.diffuseTexture);
          mat.addTexture(
              new Texture(
                  getOnlyFileName(matDef.diffuseTexture), BitmapFactory.decodeFile(filePath)));
        }
      }
      if (hasBump) {
        if (mFile == null) {
          int identifier =
              mResources.getIdentifier(
                  getFileNameWithoutExtension(matDef.bumpTexture), "drawable", mResourcePackage);
          mat.addTexture(new NormalMapTexture(identifier));
        } else {
          String filePath =
              mFile.getParent() + File.separatorChar + getOnlyFileName(matDef.bumpTexture);
          mat.addTexture(
              new NormalMapTexture(
                  getOnlyFileName(matDef.bumpTexture), BitmapFactory.decodeFile(filePath)));
        }
      }
      if (hasSpecularTexture) {
        if (mFile == null) {
          int identifier =
              mResources.getIdentifier(
                  getFileNameWithoutExtension(matDef.specularColorTexture),
                  "drawable",
                  mResourcePackage);
          mat.addTexture(new SpecularMapTexture(identifier));
        } else {
          String filePath =
              mFile.getParent() + File.separatorChar + getOnlyFileName(matDef.specularColorTexture);
          mat.addTexture(
              new SpecularMapTexture(
                  getOnlyFileName(matDef.specularColorTexture),
                  BitmapFactory.decodeFile(filePath)));
        }
      }
    }
  @Override
  public LoaderOBJ parse() throws ParsingException {
    super.parse();
    BufferedReader buffer = null;
    if (mFile == null) {
      InputStream fileIn = mResources.openRawResource(mResourceId);
      buffer = new BufferedReader(new InputStreamReader(fileIn));
    } else {
      try {
        buffer = new BufferedReader(new FileReader(mFile));
      } catch (FileNotFoundException e) {
        RajLog.e("[" + getClass().getCanonicalName() + "] Could not find file.");
        e.printStackTrace();
      }
    }
    String line;
    ObjIndexData currObjIndexData = new ObjIndexData(new Object3D());
    ArrayList<ObjIndexData> objIndices = new ArrayList<ObjIndexData>();

    ArrayList<Float> vertices = new ArrayList<Float>();
    ArrayList<Float> texCoords = new ArrayList<Float>();
    ArrayList<Float> normals = new ArrayList<Float>();
    MaterialLib matLib = new MaterialLib();

    try {
      while ((line = buffer.readLine()) != null) {
        // Skip comments and empty lines.
        if (line.length() == 0 || line.charAt(0) == '#') continue;
        StringTokenizer parts = new StringTokenizer(line, " ");
        int numTokens = parts.countTokens();

        if (numTokens == 0) continue;
        String type = parts.nextToken();

        if (type.equals(VERTEX)) {
          vertices.add(Float.parseFloat(parts.nextToken()));
          vertices.add(Float.parseFloat(parts.nextToken()));
          vertices.add(Float.parseFloat(parts.nextToken()));
        } else if (type.equals(FACE)) {
          boolean isQuad = numTokens == 5;
          int[] quadvids = new int[4];
          int[] quadtids = new int[4];
          int[] quadnids = new int[4];

          boolean emptyVt = line.indexOf("//") > -1;
          if (emptyVt) line = line.replace("//", "/");

          parts = new StringTokenizer(line);

          parts.nextToken();
          StringTokenizer subParts = new StringTokenizer(parts.nextToken(), "/");
          int partLength = subParts.countTokens();

          boolean hasuv = partLength >= 2 && !emptyVt;
          boolean hasn = partLength == 3 || (partLength == 2 && emptyVt);
          int idx;

          for (int i = 1; i < numTokens; i++) {
            if (i > 1) subParts = new StringTokenizer(parts.nextToken(), "/");
            idx = Integer.parseInt(subParts.nextToken());

            if (idx < 0) idx = (vertices.size() / 3) + idx;
            else idx -= 1;
            if (!isQuad) currObjIndexData.vertexIndices.add(idx);
            else quadvids[i - 1] = idx;
            if (hasuv) {
              idx = Integer.parseInt(subParts.nextToken());
              if (idx < 0) idx = (texCoords.size() / 2) + idx;
              else idx -= 1;
              if (!isQuad) currObjIndexData.texCoordIndices.add(idx);
              else quadtids[i - 1] = idx;
            }
            if (hasn) {
              idx = Integer.parseInt(subParts.nextToken());
              if (idx < 0) idx = (normals.size() / 3) + idx;
              else idx -= 1;
              if (!isQuad) currObjIndexData.normalIndices.add(idx);
              else quadnids[i - 1] = idx;
            }
          }

          if (isQuad) {
            int[] indices = new int[] {0, 1, 2, 0, 2, 3};

            for (int i = 0; i < 6; ++i) {
              int index = indices[i];
              currObjIndexData.vertexIndices.add(quadvids[index]);
              currObjIndexData.texCoordIndices.add(quadtids[index]);
              currObjIndexData.normalIndices.add(quadnids[index]);
            }
          }
        } else if (type.equals(TEXCOORD)) {
          texCoords.add(Float.parseFloat(parts.nextToken()));
          texCoords.add(1f - Float.parseFloat(parts.nextToken()));
        } else if (type.equals(NORMAL)) {
          normals.add(Float.parseFloat(parts.nextToken()));
          normals.add(Float.parseFloat(parts.nextToken()));
          normals.add(Float.parseFloat(parts.nextToken()));
        } else if (type.equals(OBJECT) || type.equals(GROUP)) {
          String objName =
              parts.hasMoreTokens() ? parts.nextToken() : "Object" + (int) (Math.random() * 10000);

          if (type.equals(OBJECT)) {
            RajLog.i("Parsing object: " + objName);
            if (currObjIndexData.targetObj.getName() != null)
              currObjIndexData = new ObjIndexData(new Object3D(objName));
            else currObjIndexData.targetObj.setName(objName);
            objIndices.add(currObjIndexData);
          } else if (type.equals(GROUP)) {
            RajLog.i("Parsing group: " + objName);
            Object3D group = mRootObject.getChildByName(objName);
            if (group == null) {
              group = new Object3D(objName);
              mRootObject.addChild(group);
            }
            group.addChild(currObjIndexData.targetObj);
          }
        } else if (type.equals(MATERIAL_LIB)) {
          if (!parts.hasMoreTokens()) continue;
          String materialLibPath = parts.nextToken().replace(".", "_");
          Log.d(Wallpaper.TAG, "Found Material Lib: " + materialLibPath);
          if (mFile != null) matLib.parse(materialLibPath, null, null);
          else
            matLib.parse(
                materialLibPath,
                mResources.getResourceTypeName(mResourceId),
                mResources.getResourcePackageName(mResourceId));
        } else if (type.equals(USE_MATERIAL)) {
          currObjIndexData.materialName = parts.nextToken();
        }
      }
      buffer.close();

      if (objIndices.size() == 0) {
        objIndices.add(currObjIndexData);
      }
    } catch (IOException e) {
      throw new ParsingException(e);
    }

    int numObjects = objIndices.size();

    for (int j = 0; j < numObjects; ++j) {
      ObjIndexData oid = objIndices.get(j);

      int i;
      float[] aVertices = new float[oid.vertexIndices.size() * 3];
      float[] aTexCoords = new float[oid.texCoordIndices.size() * 2];
      float[] aNormals = new float[oid.normalIndices.size() * 3];
      float[] aColors = new float[oid.colorIndices.size() * 4];
      int[] aIndices = new int[oid.vertexIndices.size()];

      for (i = 0; i < oid.vertexIndices.size(); ++i) {
        int faceIndex = oid.vertexIndices.get(i) * 3;
        int vertexIndex = i * 3;
        try {
          aVertices[vertexIndex] = vertices.get(faceIndex);
          aVertices[vertexIndex + 1] = vertices.get(faceIndex + 1);
          aVertices[vertexIndex + 2] = vertices.get(faceIndex + 2);
          aIndices[i] = i;
        } catch (ArrayIndexOutOfBoundsException e) {
          Log.d("Rajawali", "ERREUR!! " + vertexIndex + ", " + faceIndex);
        }
      }
      if (texCoords != null && texCoords.size() > 0) {
        for (i = 0; i < oid.texCoordIndices.size(); ++i) {
          int texCoordIndex = oid.texCoordIndices.get(i) * 2;
          int ti = i * 2;
          aTexCoords[ti] = texCoords.get(texCoordIndex);
          aTexCoords[ti + 1] = texCoords.get(texCoordIndex + 1);
        }
      }
      for (i = 0; i < oid.colorIndices.size(); ++i) {
        int colorIndex = oid.colorIndices.get(i) * 4;
        int ti = i * 4;
        aTexCoords[ti] = texCoords.get(colorIndex);
        aTexCoords[ti + 1] = texCoords.get(colorIndex + 1);
        aTexCoords[ti + 2] = texCoords.get(colorIndex + 2);
        aTexCoords[ti + 3] = texCoords.get(colorIndex + 3);
      }
      for (i = 0; i < oid.normalIndices.size(); ++i) {
        int normalIndex = oid.normalIndices.get(i) * 3;
        int ni = i * 3;
        if (normals.size() == 0) {
          RajLog.e(
              "["
                  + getClass().getName()
                  + "] There are no normals specified for this model. Please re-export with normals.");
          throw new ParsingException(
              "["
                  + getClass().getName()
                  + "] There are no normals specified for this model. Please re-export with normals.");
        }
        aNormals[ni] = normals.get(normalIndex);
        aNormals[ni + 1] = normals.get(normalIndex + 1);
        aNormals[ni + 2] = normals.get(normalIndex + 2);
      }

      oid.targetObj.setData(aVertices, aNormals, aTexCoords, aColors, aIndices);
      try {
        matLib.setMaterial(oid.targetObj, oid.materialName);
      } catch (TextureException tme) {
        throw new ParsingException(tme);
      }
      if (oid.targetObj.getParent() == null) mRootObject.addChild(oid.targetObj);
    }

    if (mRootObject.getNumChildren() == 1 && !mRootObject.getChildAt(0).isContainer())
      mRootObject = mRootObject.getChildAt(0);

    return this;
  }
    public void onDrawFrame(GL10 glUnused) {
      super.onDrawFrame(glUnused);
      // -- no proper physics here, just a bad approximation to keep
      // this example as short as possible ;-)
      mRaptor.setZ(mRaptor.getZ() + 2f);
      mRaptor.setX((float) Math.sin(mTime) * 20f);
      mRaptor.setRotZ((float) Math.sin(mTime + 8f) * -30f);
      mRaptor.setRotY(180 + (mRaptor.getRotZ() * .1f));
      mRaptor.setRotY(180);
      mRaptor.setY((float) Math.cos(mTime) * 10f);
      mRaptor.setRotX((float) Math.cos(mTime + 1f) * -20f);

      mSphere.setZ(mRaptor.getZ());
      mTime += .01f;

      if (mRootCube.getZ() - mRaptor.getZ() <= (30 * -6)) {
        mRootCube.setZ(mRaptor.getZ());
      }
    }
    protected void initScene() {
      DirectionalLight light = new DirectionalLight(0, -.6f, .4f);
      light.setPower(1);
      getCurrentScene().addLight(light);

      // -- create sky sphere
      mSphere = new Sphere(400, 8, 8);
      Material sphereMaterial = new Material();
      try {
        sphereMaterial.addTexture(new Texture("skySphere", R.drawable.skysphere));
      } catch (TextureException e1) {
        e1.printStackTrace();
      }
      mSphere.setMaterial(sphereMaterial);
      mSphere.setDoubleSided(true);
      addChild(mSphere);

      try {
        // -- load gzipped serialized object
        ObjectInputStream ois;
        GZIPInputStream zis =
            new GZIPInputStream(mContext.getResources().openRawResource(R.raw.raptor));
        ois = new ObjectInputStream(zis);
        mRaptor = new Object3D((SerializedObject3D) ois.readObject());
        Material raptorMaterial = new Material();
        raptorMaterial.setDiffuseMethod(new DiffuseMethod.Lambert());
        raptorMaterial.enableLighting(true);
        raptorMaterial.addTexture(new Texture("raptorTex", R.drawable.raptor_texture));
        mRaptor.setMaterial(raptorMaterial);
        mRaptor.setScale(.5f);
        addChild(mRaptor);
      } catch (Exception e) {
        e.printStackTrace();
      }

      // -- create a bunch of cubes that will serve as orientation helpers

      mCubes = new Object3D[30];

      mRootCube = new Cube(1);
      Material rootCubeMaterial = new Material();
      rootCubeMaterial.setDiffuseMethod(new DiffuseMethod.Lambert());
      rootCubeMaterial.enableLighting(true);
      try {
        rootCubeMaterial.addTexture(new Texture("camouflage", R.drawable.camouflage));
      } catch (TextureException e) {
        e.printStackTrace();
      }
      mRootCube.setMaterial(rootCubeMaterial);
      mRootCube.setY(-1f);
      // -- similar objects with the same material, optimize
      mRootCube.setRenderChildrenAsBatch(true);
      addChild(mRootCube);
      mCubes[0] = mRootCube;

      for (int i = 1; i < mCubes.length; ++i) {
        Object3D cube = mRootCube.clone(true);
        cube.setY(-1f);
        cube.setZ(i * 30);
        mRootCube.addChild(cube);
        mCubes[i] = cube;
      }

      // -- create a chase camera
      // the first parameter is the camera offset
      // the second parameter is the interpolation factor
      ChaseCamera chaseCamera = new ChaseCamera(new Vector3(0, 3, 16), .1f);
      // -- tell the camera which object to chase
      chaseCamera.setObjectToChase(mRaptor);
      // -- set the far plane to 1000 so that we actually see the sky sphere
      chaseCamera.setFarPlane(1000);
      replaceAndSwitchCamera(chaseCamera, 0);
    }