b962fe1709d44c7ae79ef97aec09b01b6c59715a
[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_Kd" then
68 material.map_diffuse = read_until_eol_or_comment
69 else if token == "map_Bump" then
70 material.map_bump = read_until_eol_or_comment
71 else if token == "map_Ks" then
72 material.map_specular = read_until_eol_or_comment
73 else if token == "map_Ns" then
74 material.map_exponent = read_until_eol_or_comment
75
76 # TODO other line type headers
77 else if token == "Ns" then
78 else if token == "Ni" then
79 else if token == "sharpness" then
80 else if token == "bump" then
81 end
82 end
83 skip_eol
84 end
85
86 return mat_lib
87 end
88 end
89
90 # Material defined in a `.mtl` file
91 class MtlDef
92
93 # Name of this material
94 var name: String
95
96 # Ambient color
97 var ambient = new Vec3 is lazy
98
99 # Diffuse color
100 var diffuse = new Vec3 is lazy
101
102 # Specular color
103 var specular = new Vec3 is lazy
104
105 # Dissolved level, where 1.0 is fully visible
106 var dissolved = 1.0
107
108 # Transparency level, where 1.0 is fully invisible
109 fun transparency: Float do return 1.0 - dissolved
110
111 # Illumination model
112 var illumination_model = 0
113
114 # Diffuse map
115 var map_diffuse: nullable String = null
116
117 # Bump map or normals texture
118 var map_bump: nullable String = null
119
120 # Specular reflectivity map
121 var map_specular: nullable String = null
122
123 # Specular exponent map
124 var map_exponent: nullable String = null
125
126 # Collect non-null maps from `map_diffuse, map_bump, map_specular, map_exponent`
127 fun maps: Array[String]
128 do
129 return [for m in [map_diffuse, map_bump, map_specular, map_exponent] do if m != null then m]
130 end
131 end