Skip to content

Commit e5c67e4

Browse files
committed
gltf support - fixes #176
1 parent f532d30 commit e5c67e4

File tree

257 files changed

+45146
-91
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

257 files changed

+45146
-91
lines changed

README.md

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ Android 3D Model Viewer
44
![travis-ci badge](https://travis-ci.org/the3deers/android-3D-model-viewer.svg?branch=master)
55

66
This is a demo of OpenGL ES 2.0.
7-
It is basically an android application with a 3D engine that can load Wavefront OBJ, STL & DAE files.
7+
It is basically an android application with a 3D engine that can load Wavefront OBJ, STL, DAE & GLTF files.
88
The purpose of this application is to learn and share how to draw using OpenGL language.
99
The application does not use any third party library.
1010

1111
* Wafefront format (OBJ): https://en.wikipedia.org/wiki/Wavefront_.obj_file
1212
* STereoLithography format (STL): https://en.wikipedia.org/wiki/STL_(file_format)
1313
* Collada format (DAE): https://en.wikipedia.org/wiki/COLLADA
14+
* GLTF format (gltf): https://www.khronos.org/gltf/
1415

1516

16-
News (12/09/2022)
17+
News (17/09/2022)
1718
=================
1819

19-
* New version released 3.3.1
20+
* New version released 3.4.0
2021
* New orthographic, isometric and free camera views
21-
* Interactive object orientation
22-
* Texture issues fixed
22+
* GLTF basic support :)
2323

2424
Demo
2525
====
@@ -69,37 +69,43 @@ Whats next
6969
Features
7070
========
7171

72-
- Supports >= Android 4.0.1 (Ice Cream Sandwich) - Min API Level 14 -> Target API Level 28
73-
- OpenGL ES 2.0 API
74-
- Formats: OBJ (wavefront), STL (STereoLithography) & DAE (Collada-BETA)
75-
- calculation of normals
76-
- transformations: scaling, rotation, translation, orientation
77-
- colors
78-
- textures
79-
- lighting
80-
- wireframe + points mode
81-
- holes
82-
- smoothing
83-
- bounding box
84-
- skybox
85-
- object pick
86-
- camera support
87-
- perspective, orthographic and isometric views
88-
- tap to select object
89-
- drag to move camera
90-
- rotate with 2 fingers to rotate camera
91-
- pinch & spread to zoom in/out the camera
92-
- skeletal animations (collada dae)
93-
- ray collision detection
94-
- stereoscopic 3D: anaglyph + cardboard
95-
- other:
96-
- file explorer
97-
- repository explorer
98-
- texture loader
99-
- lightweight: only 1.3 Megabyte (embedded models excluded)
100-
101-
102-
72+
- [x] Supports >= Android 4.1 (Ice Cream Sandwich) - Min API Level 16 -> Target API Level 31
73+
- [x] OpenGL ES 2.0 API
74+
- [x] Multiple Formats:
75+
- [x] OBJ (wavefront)
76+
- [x] STL (STereoLithography)
77+
- [x] DAE (Collada-BETA)
78+
- [x] GLTF (GL Transmission Format)
79+
- [x] Vertex Normals support
80+
- [x] Transformation support: scaling, rotation, translation, orientation
81+
- [x] Colors support
82+
- [x] Textures support
83+
- [x] Lighting support
84+
- [x] Multiple Rendering Modes
85+
- [x] triangles
86+
- [x] wireframe
87+
- [x] point cloud
88+
- [x] skeleton
89+
- [x] camera support
90+
- [x] perspective
91+
- [x] orthographic
92+
- [x] isometric views
93+
- [x] free
94+
- [x] skeletal animations (collada dae)
95+
- [x] ray collision detection
96+
- [x] stereoscopic 3D: anaglyph + cardboard
97+
- [x] other:
98+
- [x] Polygon with holes
99+
- [x] Smoothing
100+
- [x] Bounding box
101+
- [x] Skybox
102+
- [x] Object picking
103+
- [x] file explorer
104+
- [x] repository explorer
105+
- [x] texture loader
106+
- [x] lightweight: only 1.3 Megabyte (embedded models excluded)
107+
108+
103109
Try it
104110
======
105111

@@ -128,6 +134,7 @@ Screenshots
128134
![Screenshot3](screenshots/screenshot3.png)
129135
![Screenshot4](screenshots/screenshot4.png)
130136
![Screenshot5](screenshots/screenshot5.png)
137+
![Screenshot6](screenshots/screenshot_gltf.png)
131138
![cowboy.gif](screenshots/cowboy.gif)
132139
![stormtrooper.gif](screenshots/stormtrooper.gif)
133140
![Screenshot6](screenshots/screenshot6-3d.png)
@@ -166,6 +173,7 @@ Acknowledgement
166173
* For teaching how animation engine works: https://github.com/TheThinMatrix/OpenGL-Animation
167174
* To the lot of user's feedback: https://github.com/the3deers/android-3D-model-viewer/issues
168175
* To the many infinite educational resources found in Internet for free :)
176+
* For the GLTF parser https://github.com/javagl/JglTF
169177

170178

171179
Licenses
@@ -175,8 +183,9 @@ The following copyright notice and this permission notice shall be included in a
175183
copies or substantial portions of the Software.
176184

177185

178-
MIT License - Copyright (c) 2020 The 3Deers - https://github.com/the3deers
186+
MIT License - Copyright (c) 2022 The 3Deers - https://github.com/the3deers
179187
GNU LGPL v2.1 Copyright (c) 2001, 2002 Dipl. Ing. P. Szawlowski - STL Parser
188+
MIT License - https://github.com/javagl/JglTF - GLTF Parser
180189
ISC License - Earcut - https://github.com/the3deers/earcut
181190

182191

@@ -195,6 +204,8 @@ ChangeLog
195204

196205
(f) fixed, (i) improved, (n) new feature
197206

207+
- 3.4.0 (17/09/2022)
208+
- (n) GLTF basic support
198209
- 3.3.1 (12/09/2022)
199210
- (f) fixed texture issue + color issue + blending issue. fixed #214
200211
- (f) fixed texture issue #204
3.76 MB
Binary file not shown.
-3.33 MB
Binary file not shown.
-1.58 MB
Binary file not shown.

app/src/main/java/org/andresoviedo/app/model3D/view/MenuActivity.java

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,30 @@
2525
import org.andresoviedo.util.android.ContentUtils;
2626
import org.andresoviedo.util.android.FileUtils;
2727
import org.andresoviedo.util.view.TextActivity;
28+
import org.json.JSONArray;
29+
import org.json.JSONException;
30+
import org.json.JSONObject;
2831

2932
import java.io.File;
3033
import java.io.IOException;
3134
import java.net.MalformedURLException;
3235
import java.net.URI;
3336
import java.net.URISyntaxException;
3437
import java.net.URL;
38+
import java.util.ArrayList;
39+
import java.util.Collections;
3540
import java.util.HashMap;
41+
import java.util.Iterator;
3642
import java.util.List;
3743
import java.util.Locale;
3844
import java.util.Map;
3945

46+
import de.javagl.jgltf.model.io.IO;
47+
4048
public class MenuActivity extends ListActivity {
4149

4250
private static final URL REPO_URL = createURL("https://github.com/the3deers/android-3D-model-viewer/raw/master/models/index");
51+
private static final URL REPO_KHRONOS_URL = createURL("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/model-index.json");
4352
private static final int REQUEST_READ_EXTERNAL_STORAGE = 1000;
4453
private static final int REQUEST_INTERNET_ACCESS = 1001;
4554
private static final int REQUEST_READ_CONTENT_PROVIDER = 1002;
@@ -48,7 +57,7 @@ public class MenuActivity extends ListActivity {
4857
private static final int REQUEST_CODE_OPEN_MATERIAL = 1102;
4958
private static final int REQUEST_CODE_OPEN_TEXTURE = 1103;
5059
private static final int REQUEST_CODE_ADD_FILES = 1200;
51-
private static final String SUPPORTED_FILE_TYPES_REGEX = "(?i).*\\.(obj|stl|dae|index)";
60+
private static final String SUPPORTED_FILE_TYPES_REGEX = "(?i).*\\.(obj|stl|dae|gltf|index)";
5261

5362

5463
private enum Action {
@@ -155,7 +164,7 @@ private void loadModel() {
155164
if (which == 0) {
156165
loadModelFromAssets();
157166
} else if (which == 1) {
158-
loadModelFromRepository(REPO_URL);
167+
loadModelFromRepository();
159168
} else if (which == 2) {
160169
loadModelFromContentProvider();
161170
} else {
@@ -165,6 +174,31 @@ private void loadModel() {
165174

166175
}
167176

177+
private void loadModelFromRepository() {
178+
179+
if (true){
180+
if (AndroidUtils.checkPermission(this, Manifest.permission.INTERNET, REQUEST_INTERNET_ACCESS)) {
181+
new LoadRepoIndexTask().execute(REPO_URL);
182+
}
183+
return;
184+
}
185+
186+
// testing purposes only
187+
ContentUtils.showListDialog(this, "Choose Repository",
188+
new String[]{"android-3D-model-viewer", "Khronos glTF-Sample-Models"},
189+
(DialogInterface dialog, int which) -> {
190+
if (which == 0) {
191+
if (AndroidUtils.checkPermission(this, Manifest.permission.INTERNET, REQUEST_INTERNET_ACCESS)) {
192+
new LoadRepoIndexTask().execute(REPO_URL);
193+
}
194+
} else if (which == 1) {
195+
if (AndroidUtils.checkPermission(this, Manifest.permission.INTERNET, REQUEST_INTERNET_ACCESS)) {
196+
new LoadRepoKhronos().execute(REPO_KHRONOS_URL);
197+
}
198+
}
199+
});
200+
}
201+
168202
private void loadModelFromAssets() {
169203
AssetUtils.createChooserDialog(this, "Select file", null, "models", SUPPORTED_FILE_TYPES_REGEX,
170204
(String file) -> {
@@ -181,6 +215,77 @@ private void loadModelFromRepository(URL url) {
181215
}
182216
}
183217

218+
class LoadRepoKhronos extends AsyncTask<URL, Integer, List<String>> {
219+
220+
private final ProgressDialog dialog;
221+
private AlertDialog.Builder chooser;
222+
223+
public LoadRepoKhronos() {
224+
this.dialog = new ProgressDialog(MenuActivity.this);
225+
}
226+
227+
@Override
228+
protected void onPreExecute() {
229+
super.onPreExecute();
230+
this.dialog.setMessage("Loading...");
231+
this.dialog.setCancelable(false);
232+
this.dialog.show();
233+
}
234+
235+
@Override
236+
protected List<String> doInBackground(URL... urls) {
237+
238+
try {
239+
// read json
240+
final String json = ContentUtils.read(urls[0]);
241+
242+
// parse json
243+
final JSONArray jsonArray = new JSONArray(json);
244+
245+
final List<String> files = new ArrayList<>();
246+
for (int i=0; i < jsonArray.length(); i++){
247+
final JSONObject jsonObject = jsonArray.getJSONObject(i);
248+
final String name = jsonObject.getString("name");
249+
JSONObject variants = jsonObject.getJSONObject("variants");
250+
for (Iterator<String> it = variants.keys(); it.hasNext(); ) {
251+
final String variant = it.next();
252+
final URI baseUri = IO.getParent(urls[0].toURI());
253+
final String filename = variants.getString(variant);
254+
final String uri = baseUri
255+
+ name + "/"+ variant + "/" + filename;
256+
files.add(uri);
257+
}
258+
}
259+
260+
// chooser
261+
chooser = ContentUtils.createChooserDialog(MenuActivity.this, "Select file", null,
262+
files, null, SUPPORTED_FILE_TYPES_REGEX,
263+
(String file) -> {
264+
if (file != null) {
265+
launchModelRendererActivity(Uri.parse(file));
266+
}
267+
});
268+
return files;
269+
} catch (JSONException | URISyntaxException e) {
270+
e.printStackTrace();
271+
return Collections.emptyList();
272+
}
273+
}
274+
275+
@Override
276+
protected void onPostExecute(List<String> strings) {
277+
if (dialog.isShowing()) {
278+
dialog.dismiss();
279+
}
280+
if (strings == null) {
281+
Toast.makeText(MenuActivity.this, "Couldn't load repo index", Toast.LENGTH_LONG).show();
282+
return;
283+
}
284+
285+
chooser.create().show();
286+
}
287+
}
288+
184289
class LoadRepoIndexTask extends AsyncTask<URL, Integer, List<String>> {
185290

186291
private final ProgressDialog dialog;
@@ -291,7 +396,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
291396
loadModelFromContentProvider();
292397
break;
293398
case REQUEST_INTERNET_ACCESS:
294-
loadModelFromRepository(REPO_URL);
399+
loadModelFromRepository();
295400
break;
296401
case REQUEST_CODE_LOAD_MODEL:
297402
if (resultCode != RESULT_OK) {

engine/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ android {
3232
dependencies {
3333
implementation fileTree(dir: 'libs', include: ['*.jar'])
3434

35-
implementation 'androidx.core:core:1.7.0'
35+
implementation 'androidx.core:core:1.8.0'
36+
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4'
3637
testImplementation 'junit:junit:4.13.2'
3738
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
3839
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

0 commit comments

Comments
 (0)