Merge "Adding better navigation to model viewer (pinch to zoom, rotations) Adding ability to load a3d files from disk."
This commit is contained in:
committed by
Android (Google) Code Review
commit
2e10374dce
@@ -3,14 +3,19 @@
|
||||
package="com.android.modelviewer">
|
||||
<application android:label="ModelViewer">
|
||||
<activity android:name="SimpleModel"
|
||||
android:label="SimpleModel"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar">
|
||||
android:label="SimpleModel">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="A3DSelector"
|
||||
android:label="A3DSelector"
|
||||
android:hardwareAccelerated="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="SceneGraph"
|
||||
android:label="SceneGraph"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar">
|
||||
|
||||
25
libs/rs/java/ModelViewer/res/menu/loader_menu.xml
Normal file
25
libs/rs/java/ModelViewer/res/menu/loader_menu.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/load_model"
|
||||
android:title="@string/load_model" />
|
||||
<item android:id="@+id/display_options"
|
||||
android:title="@string/display_options" />
|
||||
</menu>
|
||||
24
libs/rs/java/ModelViewer/res/values/strings.xml
Normal file
24
libs/rs/java/ModelViewer/res/values/strings.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<skip />
|
||||
<string name="load_model">Load Model</string>
|
||||
<string name="display_options">Display Options</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* 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.android.modelviewer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* A list view where the last item the user clicked is placed in
|
||||
* the "activated" state, causing its background to highlight.
|
||||
*/
|
||||
public class A3DSelector extends ListActivity {
|
||||
|
||||
File[] mCurrentSubList;
|
||||
File mCurrentFile;
|
||||
|
||||
class A3DFilter implements FileFilter {
|
||||
public boolean accept(File file) {
|
||||
if (file.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
return file.getName().endsWith(".a3d");
|
||||
}
|
||||
}
|
||||
|
||||
private void populateList(File file) {
|
||||
|
||||
mCurrentFile = file;
|
||||
setTitle(mCurrentFile.getAbsolutePath() + "/*.a3d");
|
||||
List<String> names = new ArrayList<String>();
|
||||
names.add("..");
|
||||
|
||||
mCurrentSubList = mCurrentFile.listFiles(new A3DFilter());
|
||||
|
||||
if (mCurrentSubList != null) {
|
||||
for (int i = 0; i < mCurrentSubList.length; i ++) {
|
||||
String fileName = mCurrentSubList[i].getName();
|
||||
if (mCurrentSubList[i].isDirectory()) {
|
||||
fileName = "/" + fileName;
|
||||
}
|
||||
names.add(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the built-in layout for showing a list item with a single
|
||||
// line of text whose background is changes when activated.
|
||||
setListAdapter(new ArrayAdapter<String>(this,
|
||||
android.R.layout.simple_list_item_activated_1, names));
|
||||
getListView().setTextFilterEnabled(true);
|
||||
|
||||
// Tell the list view to show one checked/activated item at a time.
|
||||
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
populateList(new File("/sdcard/"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
if (position == 0) {
|
||||
File parent = mCurrentFile.getParentFile();
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
populateList(parent);
|
||||
return;
|
||||
}
|
||||
|
||||
// the first thing in list is parent directory
|
||||
File selectedFile = mCurrentSubList[position - 1];
|
||||
if (selectedFile.isDirectory()) {
|
||||
populateList(selectedFile);
|
||||
return;
|
||||
}
|
||||
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.setData(Uri.fromFile(selectedFile));
|
||||
setResult(RESULT_OK, resultIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.renderscript.RenderScript;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -31,9 +32,11 @@ import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.lang.Runtime;
|
||||
|
||||
@@ -67,5 +70,45 @@ public class SimpleModel extends Activity {
|
||||
mView.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.loader_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle item selection
|
||||
switch (item.getItemId()) {
|
||||
case R.id.load_model:
|
||||
loadModel();
|
||||
return true;
|
||||
case R.id.display_options:
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int FIND_A3D_MODEL = 10;
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (requestCode == FIND_A3D_MODEL) {
|
||||
Uri selectedImageUri = data.getData();
|
||||
Log.e("Selected Path: ", selectedImageUri.getPath());
|
||||
mView.loadA3DFile(selectedImageUri.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadModel() {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_PICK);
|
||||
intent.setClassName("com.android.modelviewer",
|
||||
"com.android.modelviewer.A3DSelector");
|
||||
startActivityForResult(intent, FIND_A3D_MODEL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,24 +26,20 @@ import android.util.Log;
|
||||
|
||||
public class SimpleModelRS {
|
||||
|
||||
private final int STATE_LAST_FOCUS = 1;
|
||||
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
int mRotation;
|
||||
|
||||
public SimpleModelRS() {
|
||||
}
|
||||
|
||||
public void init(RenderScriptGL rs, Resources res, int width, int height) {
|
||||
public void init(RenderScriptGL rs, Resources res) {
|
||||
mRS = rs;
|
||||
mRes = res;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mRotation = 0;
|
||||
initRS();
|
||||
}
|
||||
|
||||
public void surfaceChanged() {
|
||||
mRS.getWidth();
|
||||
mRS.getHeight();
|
||||
}
|
||||
|
||||
private Resources mRes;
|
||||
private RenderScriptGL mRS;
|
||||
private Sampler mSampler;
|
||||
@@ -55,34 +51,23 @@ public class SimpleModelRS {
|
||||
private Allocation mGridImage;
|
||||
private Allocation mAllocPV;
|
||||
|
||||
private Mesh mMesh;
|
||||
|
||||
private Font mItalic;
|
||||
private Allocation mTextAlloc;
|
||||
|
||||
private ScriptField_MeshInfo mMeshes;
|
||||
private ScriptC_simplemodel mScript;
|
||||
|
||||
int mLastX;
|
||||
int mLastY;
|
||||
|
||||
public void touchEvent(int x, int y) {
|
||||
int dx = mLastX - x;
|
||||
if (Math.abs(dx) > 50 || Math.abs(dx) < 3) {
|
||||
dx = 0;
|
||||
}
|
||||
public void onActionDown(float x, float y) {
|
||||
mScript.invoke_onActionDown(x, y);
|
||||
}
|
||||
|
||||
mRotation -= dx;
|
||||
if (mRotation > 360) {
|
||||
mRotation -= 360;
|
||||
}
|
||||
if (mRotation < 0) {
|
||||
mRotation += 360;
|
||||
}
|
||||
public void onActionScale(float scale) {
|
||||
mScript.invoke_onActionScale(scale);
|
||||
}
|
||||
|
||||
mScript.set_gRotate((float)mRotation);
|
||||
|
||||
mLastX = x;
|
||||
mLastY = y;
|
||||
public void onActionMove(float x, float y) {
|
||||
mScript.invoke_onActionMove(x, y);
|
||||
}
|
||||
|
||||
private void initPFS() {
|
||||
@@ -130,12 +115,48 @@ public class SimpleModelRS {
|
||||
mScript.set_gTGrid(mGridImage);
|
||||
}
|
||||
|
||||
private void initTextAllocation() {
|
||||
String allocString = "Displaying file: R.raw.robot";
|
||||
private void initTextAllocation(String fileName) {
|
||||
String allocString = "Displaying file: " + fileName;
|
||||
mTextAlloc = Allocation.createFromString(mRS, allocString, Allocation.USAGE_SCRIPT);
|
||||
mScript.set_gTextAlloc(mTextAlloc);
|
||||
}
|
||||
|
||||
private void initMeshes(FileA3D model) {
|
||||
int numEntries = model.getIndexEntryCount();
|
||||
int numMeshes = 0;
|
||||
for (int i = 0; i < numEntries; i ++) {
|
||||
FileA3D.IndexEntry entry = model.getIndexEntry(i);
|
||||
if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
|
||||
numMeshes ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numMeshes > 0) {
|
||||
mMeshes = new ScriptField_MeshInfo(mRS, numMeshes);
|
||||
|
||||
for (int i = 0; i < numEntries; i ++) {
|
||||
FileA3D.IndexEntry entry = model.getIndexEntry(i);
|
||||
if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
|
||||
Mesh mesh = entry.getMesh();
|
||||
mMeshes.set_mMesh(i, mesh, false);
|
||||
mMeshes.set_mNumIndexSets(i, mesh.getPrimitiveCount(), false);
|
||||
}
|
||||
}
|
||||
mMeshes.copyAll();
|
||||
} else {
|
||||
throw new RSRuntimeException("No valid meshes in file");
|
||||
}
|
||||
|
||||
mScript.bind_gMeshes(mMeshes);
|
||||
mScript.invoke_updateMeshInfo();
|
||||
}
|
||||
|
||||
public void loadA3DFile(String path) {
|
||||
FileA3D model = FileA3D.createFromFile(mRS, path);
|
||||
initMeshes(model);
|
||||
initTextAllocation(path);
|
||||
}
|
||||
|
||||
private void initRS() {
|
||||
|
||||
mScript = new ScriptC_simplemodel(mRS, mRes, R.raw.simplemodel);
|
||||
@@ -147,18 +168,12 @@ public class SimpleModelRS {
|
||||
loadImage();
|
||||
|
||||
FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
|
||||
FileA3D.IndexEntry entry = model.getIndexEntry(0);
|
||||
if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
|
||||
Log.e("rs", "could not load model");
|
||||
} else {
|
||||
mMesh = (Mesh)entry.getObject();
|
||||
mScript.set_gTestMesh(mMesh);
|
||||
}
|
||||
initMeshes(model);
|
||||
|
||||
mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8);
|
||||
mScript.set_gItalic(mItalic);
|
||||
|
||||
initTextAllocation();
|
||||
initTextAllocation("R.raw.robot");
|
||||
|
||||
mRS.bindRootScript(mScript);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,81 +16,129 @@
|
||||
|
||||
package com.android.modelviewer;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import android.renderscript.RSSurfaceView;
|
||||
import android.renderscript.RenderScript;
|
||||
import android.renderscript.RenderScriptGL;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.util.Log;
|
||||
|
||||
public class SimpleModelView extends RSSurfaceView {
|
||||
|
||||
public SimpleModelView(Context context) {
|
||||
super(context);
|
||||
//setFocusable(true);
|
||||
}
|
||||
|
||||
private RenderScriptGL mRS;
|
||||
private SimpleModelRS mRender;
|
||||
|
||||
private ScaleGestureDetector mScaleDetector;
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
|
||||
super.surfaceChanged(holder, format, w, h);
|
||||
private static final int INVALID_POINTER_ID = -1;
|
||||
private int mActivePointerId = INVALID_POINTER_ID;
|
||||
|
||||
public SimpleModelView(Context context) {
|
||||
super(context);
|
||||
ensureRenderScript();
|
||||
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
|
||||
}
|
||||
|
||||
private void ensureRenderScript() {
|
||||
if (mRS == null) {
|
||||
RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
|
||||
sc.setDepth(16, 24);
|
||||
mRS = createRenderScriptGL(sc);
|
||||
mRS.setSurface(holder, w, h);
|
||||
mRender = new SimpleModelRS();
|
||||
mRender.init(mRS, getResources(), w, h);
|
||||
mRender.init(mRS, getResources());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
ensureRenderScript();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
|
||||
super.surfaceChanged(holder, format, w, h);
|
||||
mRender.surfaceChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
mRender = null;
|
||||
if (mRS != null) {
|
||||
mRS = null;
|
||||
destroyRenderScriptGL();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
// break point at here
|
||||
// this method doesn't work when 'extends View' include 'extends ScrollView'.
|
||||
return super.onKeyDown(keyCode, event);
|
||||
public void loadA3DFile(String path) {
|
||||
mRender.loadA3DFile(path);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev)
|
||||
{
|
||||
boolean ret = true;
|
||||
int act = ev.getAction();
|
||||
if (act == ev.ACTION_UP) {
|
||||
ret = false;
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
mScaleDetector.onTouchEvent(ev);
|
||||
|
||||
boolean ret = false;
|
||||
float x = ev.getX();
|
||||
float y = ev.getY();
|
||||
|
||||
final int action = ev.getAction();
|
||||
|
||||
switch (action & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
mRender.onActionDown(x, y);
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
if (!mScaleDetector.isInProgress()) {
|
||||
mRender.onActionMove(x, y);
|
||||
}
|
||||
mRender.onActionDown(x, y);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_UP: {
|
||||
mActivePointerId = INVALID_POINTER_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
mActivePointerId = INVALID_POINTER_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
|
||||
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
final int pointerId = ev.getPointerId(pointerIndex);
|
||||
if (pointerId == mActivePointerId) {
|
||||
// This was our active pointer going up. Choose a new
|
||||
// active pointer and adjust accordingly.
|
||||
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
|
||||
x = ev.getX(newPointerIndex);
|
||||
y = ev.getY(newPointerIndex);
|
||||
mRender.onActionDown(x, y);
|
||||
mActivePointerId = ev.getPointerId(newPointerIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mRender.touchEvent((int)ev.getX(), (int)ev.getY());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
mRender.onActionScale(detector.getScaleFactor());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2009 The Android Open Source Project
|
||||
// Copyright (C) 2011 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -22,17 +22,112 @@ rs_program_vertex gPVBackground;
|
||||
rs_program_fragment gPFBackground;
|
||||
|
||||
rs_allocation gTGrid;
|
||||
rs_mesh gTestMesh;
|
||||
|
||||
rs_program_store gPFSBackground;
|
||||
|
||||
float gRotate;
|
||||
|
||||
rs_font gItalic;
|
||||
rs_allocation gTextAlloc;
|
||||
|
||||
typedef struct MeshInfo {
|
||||
rs_mesh mMesh;
|
||||
int mNumIndexSets;
|
||||
float3 bBoxMin;
|
||||
float3 bBoxMax;
|
||||
} MeshInfo_t;
|
||||
|
||||
MeshInfo_t *gMeshes;
|
||||
|
||||
static float3 gLookAt;
|
||||
|
||||
static float gRotateX;
|
||||
static float gRotateY;
|
||||
static float gZoom;
|
||||
|
||||
static float gLastX;
|
||||
static float gLastY;
|
||||
|
||||
void onActionDown(float x, float y) {
|
||||
gLastX = x;
|
||||
gLastY = y;
|
||||
}
|
||||
|
||||
void onActionScale(float scale) {
|
||||
|
||||
gZoom *= 1.0f / scale;
|
||||
gZoom = max(0.1f, min(gZoom, 500.0f));
|
||||
}
|
||||
|
||||
void onActionMove(float x, float y) {
|
||||
float dx = gLastX - x;
|
||||
float dy = gLastY - y;
|
||||
|
||||
if (fabs(dy) <= 2.0f) {
|
||||
dy = 0.0f;
|
||||
}
|
||||
if (fabs(dx) <= 2.0f) {
|
||||
dx = 0.0f;
|
||||
}
|
||||
|
||||
gRotateY -= dx;
|
||||
if (gRotateY > 360) {
|
||||
gRotateY -= 360;
|
||||
}
|
||||
if (gRotateY < 0) {
|
||||
gRotateY += 360;
|
||||
}
|
||||
|
||||
gRotateX -= dy;
|
||||
gRotateX = min(gRotateX, 80.0f);
|
||||
gRotateX = max(gRotateX, -80.0f);
|
||||
|
||||
gLastX = x;
|
||||
gLastY = y;
|
||||
}
|
||||
|
||||
void init() {
|
||||
gRotate = 0.0f;
|
||||
gRotateX = 0.0f;
|
||||
gRotateY = 0.0f;
|
||||
gZoom = 50.0f;
|
||||
gLookAt = 0.0f;
|
||||
}
|
||||
|
||||
void updateMeshInfo() {
|
||||
rs_allocation allMeshes = rsGetAllocation(gMeshes);
|
||||
int size = rsAllocationGetDimX(allMeshes);
|
||||
gLookAt = 0.0f;
|
||||
float minX, minY, minZ, maxX, maxY, maxZ;
|
||||
for (int i = 0; i < size; i++) {
|
||||
MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
|
||||
rsgMeshComputeBoundingBox(info->mMesh,
|
||||
&minX, &minY, &minZ,
|
||||
&maxX, &maxY, &maxZ);
|
||||
info->bBoxMin = (minX, minY, minZ);
|
||||
info->bBoxMax = (maxX, maxY, maxZ);
|
||||
gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f;
|
||||
}
|
||||
gLookAt = gLookAt / (float)size;
|
||||
}
|
||||
|
||||
static void renderAllMeshes() {
|
||||
rs_allocation allMeshes = rsGetAllocation(gMeshes);
|
||||
int size = rsAllocationGetDimX(allMeshes);
|
||||
gLookAt = 0.0f;
|
||||
float minX, minY, minZ, maxX, maxY, maxZ;
|
||||
for (int i = 0; i < size; i++) {
|
||||
MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
|
||||
rsgDrawMesh(info->mMesh);
|
||||
}
|
||||
}
|
||||
|
||||
void drawDescription() {
|
||||
uint width = rsgGetWidth();
|
||||
uint height = rsgGetHeight();
|
||||
int left = 0, right = 0, top = 0, bottom = 0;
|
||||
|
||||
rsgBindFont(gItalic);
|
||||
|
||||
rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom);
|
||||
rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom);
|
||||
}
|
||||
|
||||
int root(int launchID) {
|
||||
@@ -43,7 +138,7 @@ int root(int launchID) {
|
||||
rsgBindProgramVertex(gPVBackground);
|
||||
rs_matrix4x4 proj;
|
||||
float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
|
||||
rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
|
||||
rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f);
|
||||
rsgProgramVertexLoadProjectionMatrix(&proj);
|
||||
|
||||
rsgBindProgramFragment(gPFBackground);
|
||||
@@ -52,20 +147,15 @@ int root(int launchID) {
|
||||
|
||||
rs_matrix4x4 matrix;
|
||||
rsMatrixLoadIdentity(&matrix);
|
||||
// Position our model on the screen
|
||||
rsMatrixTranslate(&matrix, 0.0f, -0.3f, -10.0f);
|
||||
rsMatrixScale(&matrix, 0.2f, 0.2f, 0.2f);
|
||||
rsMatrixRotate(&matrix, 25.0f, 1.0f, 0.0f, 0.0f);
|
||||
rsMatrixRotate(&matrix, gRotate, 0.0f, 1.0f, 0.0f);
|
||||
// Position our models on the screen
|
||||
rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom);
|
||||
rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f);
|
||||
rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
|
||||
rsgProgramVertexLoadModelMatrix(&matrix);
|
||||
|
||||
rsgDrawMesh(gTestMesh);
|
||||
renderAllMeshes();
|
||||
|
||||
rsgFontColor(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
rsgDrawText("Renderscript model test", 30, 695);
|
||||
|
||||
rsgBindFont(gItalic);
|
||||
rsgDrawText(gTextAlloc, 30, 730);
|
||||
drawDescription();
|
||||
|
||||
return 10;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user