Skip to content

Commit 12fb7a6

Browse files
committed
Merge: Intro parsers to load 3D models from .obj and .mtl files
Intro parsers to load 3D models from the ASCII based format of .obj and .mtl files. Also as support intro a new kind of asset, `app::TextAsset`, with lazy loading in the style of `Sound` and `Texture`. Model parsing services will be used by the 3D API of gamnit to load 3D models generated by modeler tools like Blender. The services in `gamnit::model_parsers` are independent of gamnit. However since they are game related, it is a nice package to classify them in. They still can be used by any other 3D graphics engine, as `gamnit::network` which is also independent but game oriented. This adds a small duplication in their representation because a model is stored differently once loaded in gamnit. But the format in gamnit is so low-level (only arrays of Float) that we need an intermediate representation to triangulate faces and stuff like that. Services of `model_parser_base` may be moved to other modules in the future as needed. The services added to `StringProcessor`, may be useful to other parsers and thus it could be moved up to `parser_base`. `Vec3` and `Vec4` apply an API similar to `vec3 & vec4` of GLSL. I may move them up to gamnit or glesv2 and add more services to transform from and to points, colors and other float based data vectors. Pull-Request: #1918 Reviewed-by: Alexandre Blondin Massé <alexandre.blondin.masse@gmail.com> Reviewed-by: Jean Privat <jean@pryen.org>
2 parents c225099 + 6efb4ef commit 12fb7a6

File tree

14 files changed

+705
-12
lines changed

14 files changed

+705
-12
lines changed

lib/android/android.nit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import platform
2424
import native_app_glue
2525
import dalvik
2626
private import log
27+
private import assets
2728

2829
redef class App
2930
redef fun init_window

lib/android/assets.nit

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# This file is part of NIT ( http://www.nitlanguage.org ).
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Implementation of `app::assets`
16+
#
17+
# This module is a client of `assets_and_resources` as the latter
18+
# covers the services of Android.
19+
module assets
20+
21+
intrude import assets_and_resources
22+
23+
redef class TextAsset
24+
redef fun load
25+
do
26+
jni_env.push_local_frame 8
27+
28+
var manager = app.asset_manager
29+
var stream = manager.open(path)
30+
if stream.is_java_null then
31+
self.error = new Error("Failed to open asset at '{path}'")
32+
jni_env.pop_local_frame
33+
self.to_s = ""
34+
return ""
35+
end
36+
37+
var text = stream.read_all
38+
stream.close
39+
if text.is_java_null then
40+
self.error = new Error("Failed to read content of asset file at '{path}'")
41+
jni_env.pop_local_frame
42+
self.to_s = ""
43+
return ""
44+
end
45+
46+
var content = text.to_s
47+
jni_env.pop_local_frame
48+
self.to_s = content
49+
return content
50+
end
51+
end
52+
53+
redef class NativeInputStream
54+
55+
# Read and return all the content of this stream
56+
private fun read_all: JavaString in "Java" `{
57+
// `available` returns the n of bytes currently available, not the total.
58+
// This may cause problems in the future with large asset files.
59+
try {
60+
int size = self.available();
61+
byte[] bytes = new byte[size];
62+
self.read(bytes, 0, size);
63+
64+
return new String(bytes);
65+
} catch (java.lang.Exception exception) {
66+
exception.printStackTrace();
67+
return null;
68+
}
69+
`}
70+
end

lib/android/assets_and_resources.nit

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class AssetManager
138138

139139
# Return a string array of all the assets at the given path
140140
fun list(path: String): Array[String] do
141-
sys.jni_env.push_local_frame(1)
141+
sys.jni_env.push_local_frame(8)
142142
var java_array = native_assets_manager.list(path.to_java_string)
143143
var nit_array = new Array[String]
144144
for s in java_array do
@@ -150,16 +150,15 @@ class AssetManager
150150

151151
# Open an asset using ACCESS_STREAMING mode, returning a NativeInputStream
152152
private fun open(file_name: String): NativeInputStream do
153-
sys.jni_env.push_local_frame(1)
153+
sys.jni_env.push_local_frame(2)
154154
var return_value = native_assets_manager.open(file_name.to_java_string)
155-
sys.jni_env.pop_local_frame
156-
return return_value
155+
return return_value.pop_from_local_frame
157156
end
158157

159158
# Open an asset using it's name and returning a NativeAssetFileDescriptor
160159
# `file_name` is
161160
private fun open_fd(file_name: String): NativeAssetFileDescriptor do
162-
sys.jni_env.push_local_frame(1)
161+
sys.jni_env.push_local_frame(2)
163162
var return_value = native_assets_manager.open_fd(file_name.to_java_string).new_global_ref
164163
sys.jni_env.pop_local_frame
165164
return return_value
@@ -373,7 +372,7 @@ extern class NativeAssetFileDescriptor in "Java" `{ android.content.res.AssetFil
373372
fun declared_length: Int in "Java" `{ return (int)self.getDeclaredLength(); `}
374373
# fun extras: Bundle in "Java" `{ return self.getExtras(); `}
375374

376-
fun file_descriptor: NativeFileDescriptor in "Java" `{
375+
fun file_descriptor: NativeFileDescriptor in "Java" `{
377376
FileDescriptor fd = self.getFileDescriptor();
378377
if (fd == null) {
379378
Log.e("AssetFileDesciptorError", "Can't retrieve the FileDescriptor of this AssetFileDescriptor");

lib/android/ui/ui.nit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import nit_activity
2727

2828
import app::ui
2929
private import data_store
30+
import assets
3031

3132
redef class Control
3233
# The Android element used to implement `self`

lib/app/app.nit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@
2121
module app
2222

2323
import app_base
24+
import assets

lib/app/assets.nit

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# This file is part of NIT ( http://www.nitlanguage.org ).
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Portable services to load resources from the assets folder
16+
module assets
17+
18+
# Resource from the assets folder
19+
#
20+
# At compilation, the asset folder should be at the root of the package.
21+
# In practice, this is usually next to the folders `src` and `bin`.
22+
#
23+
# These assets are packaged with the application.
24+
abstract class Asset
25+
26+
# Path to this asset within the assets folder
27+
var path: String
28+
end
29+
30+
# Text file from the assets folder
31+
#
32+
# Use `to_s` to get the content of this asset.
33+
class TextAsset
34+
super Asset
35+
36+
# Text content of this asset
37+
redef var to_s = load is lazy
38+
39+
# Load this asset
40+
fun load: String is abstract
41+
42+
# Error on the last call to `load`, if any
43+
var error: nullable Error = null
44+
end

lib/core/collection/hash_collection.nit

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ redef class Map[K, V]
2020
new do return new HashMap[K, V]
2121
end
2222

23+
redef class Set[E]
24+
# Get an instance of `HashMap[K, V]`, the default implementation
25+
new do return new HashSet[E]
26+
end
27+
2328
# A HashCollection is an array of HashNode[K] indexed by the K hash value
2429
private abstract class HashCollection[K]
2530
type N: HashNode[K]
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# This file is part of NIT ( http://www.nitlanguage.org ).
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Services to parse models from a text description
16+
module model_parser_base
17+
18+
import parser_base
19+
20+
# Vector of 3 values, either `x, y, z`, `u, v, z` or `r, g, b`
21+
class Vec3
22+
23+
# X value
24+
var x = 0.0 is writable
25+
26+
# Y value
27+
var y = 0.0 is writable
28+
29+
# Z value
30+
var z = 0.0 is writable
31+
32+
# U value (redirection as `x`)
33+
fun u: Float do return x
34+
35+
# Set U value (redirection for `x=`)
36+
fun u=(value: Float) do x = value
37+
38+
# V value (redirection as `y`)
39+
fun v: Float do return y
40+
41+
# Set V value (redirection for `y=`)
42+
fun v=(value: Float) do y = value
43+
44+
# R value
45+
fun r: Float do return x
46+
47+
# Set R value (redirection for `x=`)
48+
fun r=(value: Float) do x = value
49+
50+
# G value
51+
fun g: Float do return y
52+
53+
# Set G value (redirection for `y=`)
54+
fun g=(value: Float) do y = value
55+
56+
# B value
57+
fun b: Float do return z
58+
59+
# Set B value (redirection for `z=`)
60+
fun b=(value: Float) do z = value
61+
62+
# Return all values into a new `Array[Float]`
63+
fun to_a: Array[Float] do return [x, y, z]
64+
65+
redef fun to_s do return "<{class_name} {x} {y} {z}>"
66+
end
67+
68+
# Vector of 4 values, either `x, y, z, w`, `u, v, z, w` or `r, g, b, a`
69+
class Vec4
70+
super Vec3
71+
72+
# W value
73+
var w = 1.0 is writable
74+
75+
# A value (redirection to `z`)
76+
fun a: Float do return z
77+
78+
# Set A value (redirection for `z=`)
79+
fun a=(value: Float) do z = value
80+
81+
# Return all values into a new `Array[Float]`
82+
redef fun to_a do return [x, y, z, w]
83+
84+
redef fun to_s do return "<{class_name} {x} {y} {z} {w}>"
85+
end
86+
87+
redef class StringProcessor
88+
# Read a single token after skipping preceding whitespaces
89+
#
90+
# Returns an empty string when at `eof`
91+
protected fun read_token: String
92+
do
93+
while not eof and src[pos].is_whitespace and src[pos] != '\n' do
94+
pos += 1
95+
end
96+
97+
var start = pos
98+
ignore_until_whitespace_or_comment
99+
var ending = pos
100+
var str = src.substring(start, ending-start)
101+
return str
102+
end
103+
104+
# Read 3 or 4 numbers and return them as a `Vec4`
105+
#
106+
# If there is no fourth value, `Vec4::w` is set to 1.0.
107+
protected fun read_vec4: Vec4
108+
do
109+
var vec = new Vec4
110+
vec.x = read_number
111+
vec.y = read_number
112+
vec.z = read_number
113+
114+
var wstr = read_token
115+
if wstr.length > 0 then
116+
vec.w = if wstr.is_numeric then wstr.to_f else 0.0
117+
else
118+
vec.w = 1.0
119+
end
120+
121+
return vec
122+
end
123+
124+
# Read 2 or 3 numbers and return them as a `Vec3`
125+
#
126+
# If there is no third value, `Vec3::z` is set to 0.0.
127+
protected fun read_vec3: Vec3
128+
do
129+
var vec = new Vec3
130+
vec.x = read_number
131+
vec.y = read_number # Make optional
132+
133+
var wstr = read_token
134+
if wstr.length > 0 then
135+
vec.z = if wstr.is_numeric then wstr.to_f else 0.0
136+
else
137+
vec.z = 0.0
138+
end
139+
140+
return vec
141+
end
142+
143+
# Advance `pos` until a whitespace or `#` is encountered
144+
protected fun ignore_until_whitespace_or_comment: Int
145+
do
146+
while src.length > pos and not src[pos].is_whitespace and src[pos] != '#' do
147+
pos += 1
148+
end
149+
return pos
150+
end
151+
152+
# Read a token and parse it as a `Float`
153+
protected fun read_number: Float
154+
do
155+
var str = read_token
156+
return if str.is_numeric then str.to_f else 0.0
157+
end
158+
159+
# Advance `pos` until the next end of line or a `#`
160+
protected fun read_until_eol_or_comment: String
161+
do
162+
ignore_whitespaces
163+
var start = pos
164+
while not eof and src[pos] != '#' and src[pos] != '\n' do
165+
pos += 1
166+
end
167+
var ending = pos
168+
var str = src.substring(start, ending-start)
169+
return str.trim
170+
end
171+
172+
# Advance `pos` to skip the next end of line
173+
protected fun skip_eol
174+
do
175+
while not eof do
176+
var c = src.chars[pos]
177+
pos += 1
178+
if c == '\n' then break
179+
end
180+
end
181+
end

0 commit comments

Comments
 (0)