lib/gamnit: add support for map_Ka in the .mtl parser
[nit.git] / lib / gamnit / model_parsers / mtl.nit
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 .mtl material files
16 module mtl
17
18 import model_parser_base
19
20 # Parser of `.mtl` files
21 #
22 # ~~~
23 # var mtl_src = """
24 # # Green material with low reflections
25 # newmtl GreenMaterial
26 # Ns 96.078431
27 # Ka 0.000000 0.000000 0.000000
28 # Kd 0.027186 0.180434 0.012088
29 # Ks 0.500000 0.500000 0.500000
30 # Ni 1.000000
31 # d 1.000000
32 # illum 2
33 # """
34 #
35 # var parser = new MtlFileParser(mtl_src)
36 # var name_to_mtls = parser.parse
37 # assert name_to_mtls.keys.join == "GreenMaterial"
38 # ~~~
39 class MtlFileParser
40 super StringProcessor
41
42 # Read and parse source and return all materials organized by their names
43 fun parse: Map[String, MtlDef]
44 do
45 var mat_lib = new Map[String, MtlDef]
46 var material: nullable MtlDef = null
47
48 while not eof do
49 var token = read_token
50 if token == "newmtl" then
51 var name = read_until_eol_or_comment
52 material = new MtlDef(name)
53 mat_lib[name] = material
54 else if material != null then
55 if token == "Ka" then
56 material.ambient = read_vec3
57 else if token == "Kd" then
58 material.diffuse = read_vec3
59 else if token == "Ks" then
60 material.specular = read_vec3
61 else if token == "d" then
62 material.dissolved = read_number
63 else if token == "Tr" then
64 material.dissolved = 1.0 - read_number
65 else if token == "illum" then
66 material.illumination_model = read_number.to_i
67 else if token == "map_Ka" then
68 material.map_ambient = read_until_eol_or_comment
69 else if token == "map_Kd" then
70 material.map_diffuse = read_until_eol_or_comment
71 else if token == "map_Bump" then
72 material.map_bump = read_until_eol_or_comment
73 else if token == "map_Ks" then
74 material.map_specular = read_until_eol_or_comment
75 else if token == "map_Ns" then
76 material.map_exponent = read_until_eol_or_comment
77
78 # TODO other line type headers
79 else if token == "Ns" then
80 else if token == "Ni" then
81 else if token == "sharpness" then
82 else if token == "bump" then
83 end
84 end
85 skip_eol
86 end
87
88 return mat_lib
89 end
90 end
91
92 # Material defined in a `.mtl` file
93 class MtlDef
94
95 # Name of this material
96 var name: String
97
98 # Ambient color
99 var ambient = new Vec3 is lazy
100
101 # Diffuse color
102 var diffuse = new Vec3 is lazy
103
104 # Specular color
105 var specular = new Vec3 is lazy
106
107 # Dissolved level, where 1.0 is fully visible
108 var dissolved = 1.0
109
110 # Transparency level, where 1.0 is fully invisible
111 fun transparency: Float do return 1.0 - dissolved
112
113 # Illumination model
114 var illumination_model = 0
115
116 # Ambient map
117 var map_ambient: nullable String = null
118
119 # Diffuse map
120 var map_diffuse: nullable String = null
121
122 # Bump map or normals texture
123 var map_bump: nullable String = null
124
125 # Specular reflectivity map
126 var map_specular: nullable String = null
127
128 # Specular exponent map
129 var map_exponent: nullable String = null
130
131 # Collect non-null maps from `map_diffuse, map_bump, map_specular, map_exponent`
132 fun maps: Array[String]
133 do
134 return [for m in [map_ambient, map_diffuse, map_bump, map_specular, map_exponent] do if m != null then m]
135 end
136 end