floorplanner-fml 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -0
- data/bin/fml2dae.rb +15 -0
- data/bin/fml2obj.rb +10 -0
- data/lib/collada/document.rb +101 -0
- data/lib/collada/geometry.rb +110 -0
- data/lib/config.yml +15 -0
- data/lib/floorplanner.rb +46 -0
- data/lib/floorplanner/area_builder.rb +42 -0
- data/lib/floorplanner/asset.rb +185 -0
- data/lib/floorplanner/collada_export.rb +118 -0
- data/lib/floorplanner/design.rb +107 -0
- data/lib/floorplanner/document.rb +66 -0
- data/lib/floorplanner/obj_export.rb +24 -0
- data/lib/floorplanner/opening3d.rb +140 -0
- data/lib/floorplanner/rib_export.rb +24 -0
- data/lib/floorplanner/svg_export.rb +25 -0
- data/lib/floorplanner/wall3d.rb +97 -0
- data/lib/floorplanner/wall_builder.rb +165 -0
- data/lib/geom.rb +13 -0
- data/lib/geom/connection.rb +14 -0
- data/lib/geom/ear_trim.rb +52 -0
- data/lib/geom/edge.rb +89 -0
- data/lib/geom/intersection.rb +38 -0
- data/lib/geom/matrix3d.rb +141 -0
- data/lib/geom/number.rb +104 -0
- data/lib/geom/plane.rb +36 -0
- data/lib/geom/polygon.rb +264 -0
- data/lib/geom/triangle.rb +38 -0
- data/lib/geom/triangle_mesh.rb +94 -0
- data/lib/geom/vertex.rb +33 -0
- data/lib/keyhole/archive.rb +36 -0
- data/views/design.dae.erb +439 -0
- data/views/design.obj.erb +17 -0
- data/views/design.rib.erb +17 -0
- data/views/design.svg.erb +42 -0
- data/xml/collada_schema_1_4.xsd +11046 -0
- data/xml/fml.rng +268 -0
- metadata +110 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module Geom
|
2
|
+
class Triangle
|
3
|
+
|
4
|
+
attr_accessor :vertices, :texcoord, :normal
|
5
|
+
|
6
|
+
def initialize(vertices,texcoord=nil,normal=nil)
|
7
|
+
unless vertices.length == 3
|
8
|
+
raise "Triangle must consist of exactly 3 vertices"
|
9
|
+
end
|
10
|
+
@normal = normal || Number3D.new
|
11
|
+
@vertices = vertices
|
12
|
+
@texcoord = texcoord
|
13
|
+
create_normal
|
14
|
+
end
|
15
|
+
|
16
|
+
def flip_normal
|
17
|
+
@normal.x = -@normal.x
|
18
|
+
@normal.y = -@normal.y
|
19
|
+
@normal.z = -@normal.z
|
20
|
+
end
|
21
|
+
|
22
|
+
def clone
|
23
|
+
Triangle.new(@vertices.collect{|v| v.clone},@texcoord.collect{|uv| uv.clone})
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def create_normal
|
28
|
+
vn0 = @vertices[0].position.clone
|
29
|
+
vn1 = @vertices[1].position.clone
|
30
|
+
vn2 = @vertices[2].position.clone
|
31
|
+
vn1.minus_eq(vn0)
|
32
|
+
vn2.minus_eq(vn0)
|
33
|
+
@normal = Number3D.cross(vn1,vn2,@normal)
|
34
|
+
@normal.normalize
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Geom
|
2
|
+
class TriangleMesh
|
3
|
+
|
4
|
+
attr_accessor(:vertices,:texcoord,:faces,:meshes,:data,:tess)
|
5
|
+
|
6
|
+
def initialize( vertices=nil, faces=nil, user_data=nil )
|
7
|
+
@data = user_data || Hash.new
|
8
|
+
@faces = faces || Array.new
|
9
|
+
@vertices = vertices || Array.new
|
10
|
+
@meshes = Array.new
|
11
|
+
|
12
|
+
@tess = EarTrim
|
13
|
+
end
|
14
|
+
|
15
|
+
def << (mesh)
|
16
|
+
@meshes << mesh
|
17
|
+
end
|
18
|
+
|
19
|
+
def vertices
|
20
|
+
result = @meshes.collect {|m| m.vertices}.flatten
|
21
|
+
result.empty? ? @vertices : result
|
22
|
+
end
|
23
|
+
|
24
|
+
def faces
|
25
|
+
result = @meshes.collect {|m| m.faces}.flatten
|
26
|
+
result.empty? ? @faces : result
|
27
|
+
end
|
28
|
+
|
29
|
+
def texcoord
|
30
|
+
result = @meshes.collect {|m| m.texcoord}.flatten
|
31
|
+
result.empty? ? @texcoord : result
|
32
|
+
end
|
33
|
+
|
34
|
+
def update
|
35
|
+
@meshes.each {|m| m.update}
|
36
|
+
end
|
37
|
+
|
38
|
+
def reverse
|
39
|
+
faces.each {|f| f.vertices.reverse! }
|
40
|
+
end
|
41
|
+
|
42
|
+
def transform_vertices(transformation)
|
43
|
+
ta = transformation.to_a
|
44
|
+
m11 = ta[0][0]
|
45
|
+
m12 = ta[0][1]
|
46
|
+
m13 = ta[0][2]
|
47
|
+
m21 = ta[1][0]
|
48
|
+
m22 = ta[1][1]
|
49
|
+
m23 = ta[1][2]
|
50
|
+
m31 = ta[2][0]
|
51
|
+
m32 = ta[2][1]
|
52
|
+
m33 = ta[2][2]
|
53
|
+
|
54
|
+
m14 = ta[0][3]
|
55
|
+
m24 = ta[1][3]
|
56
|
+
m34 = ta[2][3]
|
57
|
+
|
58
|
+
@vertices.each do |v|
|
59
|
+
vx = v.x
|
60
|
+
vy = v.y
|
61
|
+
vz = v.z
|
62
|
+
|
63
|
+
tx = vx * m11 + vy * m12 + vz * m13 + m14
|
64
|
+
ty = vx * m21 + vy * m22 + vz * m23 + m24
|
65
|
+
tz = vx * m31 + vy * m32 + vz * m33 + m34
|
66
|
+
|
67
|
+
v.x = tx
|
68
|
+
v.y = ty
|
69
|
+
v.z = tz
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def bounding_box
|
74
|
+
min = Geom::Number3D.new( 1000, 1000, 1000)
|
75
|
+
max = Geom::Number3D.new(-1000,-1000,-1000)
|
76
|
+
|
77
|
+
vertices.each do |v|
|
78
|
+
min.x = v.x if v.x < min.x
|
79
|
+
min.y = v.y if v.y < min.y
|
80
|
+
min.z = v.z if v.z < min.z
|
81
|
+
|
82
|
+
max.x = v.x if v.x > max.x
|
83
|
+
max.y = v.y if v.y > max.y
|
84
|
+
max.z = v.z if v.z > max.z
|
85
|
+
end
|
86
|
+
|
87
|
+
{ :max => max , :min => min }
|
88
|
+
end
|
89
|
+
|
90
|
+
def merge(other)
|
91
|
+
@vertices.concat other.vertices
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/geom/vertex.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Geom
|
4
|
+
class Vertex
|
5
|
+
attr_accessor(:position,:normal)
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators(:@position,
|
8
|
+
:x, :y, :z, :x=, :y=, :z=,
|
9
|
+
:distance_x, :distance_y, :distance_z, :distance, :to_floats)
|
10
|
+
def initialize(x=0.0,y=0.0,z=0.0,normal=nil)
|
11
|
+
@position = Number3D.new(x,y,z)
|
12
|
+
@normal = normal
|
13
|
+
end
|
14
|
+
|
15
|
+
def == (other)
|
16
|
+
@position == other.position
|
17
|
+
end
|
18
|
+
|
19
|
+
def equal?(other,snap)
|
20
|
+
@position.x-snap < other.x && @position.x+snap > other.x &&
|
21
|
+
@position.y-snap < other.y && @position.y+snap > other.y &&
|
22
|
+
@position.z-snap < other.z && @position.z+snap > other.z
|
23
|
+
end
|
24
|
+
|
25
|
+
def clone
|
26
|
+
Vertex.new(x,y,z)
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"#<Geom::Vertex:#{@position.to_s}>"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Keyhole
|
2
|
+
class Archive < Zip::ZipFile
|
3
|
+
DAE_CACHE_PATH = File.join(Floorplanner.config['dae_cache_path'],'dae')
|
4
|
+
IMG_CACHE_PATH = File.join(Floorplanner.config['dae_cache_path'],'textures')
|
5
|
+
|
6
|
+
def dae_path(asset_id)
|
7
|
+
FileUtils.mkdir_p DAE_CACHE_PATH
|
8
|
+
dae = entries.select{|e| e.name.match(/\.dae$/)}.first
|
9
|
+
@relative_dae_path = dae.name
|
10
|
+
@dae_path = File.join(
|
11
|
+
DAE_CACHE_PATH,
|
12
|
+
"#{asset_id}_#{File.basename(dae.name)}"
|
13
|
+
)
|
14
|
+
dae.extract(@dae_path) unless File.exists?(@dae_path)
|
15
|
+
@dae_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def image_path(asset_id,relative_to_dae,relative_out=false)
|
19
|
+
FileUtils.mkdir_p IMG_CACHE_PATH
|
20
|
+
img_path = File.join(File.dirname(@relative_dae_path),relative_to_dae)
|
21
|
+
target_path = File.join(IMG_CACHE_PATH,asset_id)
|
22
|
+
tex_path = File.join(target_path,File.basename(img_path))
|
23
|
+
|
24
|
+
unless File.exists?(tex_path)
|
25
|
+
FileUtils.mkdir_p target_path
|
26
|
+
zip_image = entries.select{|e| e.name.match(File.basename(img_path)) }.first
|
27
|
+
extract( zip_image , tex_path )
|
28
|
+
end
|
29
|
+
relative_out ? '../textures'+tex_path.gsub(IMG_CACHE_PATH,'') : tex_path
|
30
|
+
end
|
31
|
+
|
32
|
+
def destroy
|
33
|
+
File.unlink(@dae_path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,439 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
|
3
|
+
<asset>
|
4
|
+
<contributor>
|
5
|
+
<author>john doe <johnny@floorplanner.com></author>
|
6
|
+
</contributor>
|
7
|
+
<created>2006-06-21T21:23:22Z</created>
|
8
|
+
<modified>2006-06-21T21:23:22Z</modified>
|
9
|
+
<unit meter="1.00" name="meter"/>
|
10
|
+
<up_axis>Z_UP</up_axis>
|
11
|
+
</asset>
|
12
|
+
|
13
|
+
<library_cameras>
|
14
|
+
<camera id="main-cam">
|
15
|
+
<optics>
|
16
|
+
<technique_common>
|
17
|
+
<perspective>
|
18
|
+
<yfov>70</yfov>
|
19
|
+
<znear>0.1</znear>
|
20
|
+
<zfar>100.0</zfar>
|
21
|
+
</perspective>
|
22
|
+
</technique_common>
|
23
|
+
</optics>
|
24
|
+
</camera>
|
25
|
+
</library_cameras>
|
26
|
+
|
27
|
+
<library_materials id="surrounding-materials">
|
28
|
+
<material id="walls-material" name="WallsMaterial">
|
29
|
+
<instance_effect url="#walls-fx"/>
|
30
|
+
</material>
|
31
|
+
<material id="windows-material" name="WindowsMaterial">
|
32
|
+
<instance_effect url="#windows-fx"/>
|
33
|
+
</material>
|
34
|
+
<% @areas.each do |area_mesh| %>
|
35
|
+
<material id="area_<%= area_mesh.data[:id] %>-material" name="<%= area_mesh.data[:name] %>">
|
36
|
+
<instance_effect url="#area_<%= area_mesh.data[:id] %>-fx"/>
|
37
|
+
</material>
|
38
|
+
<% end %>
|
39
|
+
<% unless @xrefs; @assets.each_value do |asset| %>
|
40
|
+
<% asset.library_materials.each do |materials| %>
|
41
|
+
<%= materials.to_s %>
|
42
|
+
<% end %>
|
43
|
+
<% end; end %>
|
44
|
+
</library_materials>
|
45
|
+
|
46
|
+
<library_effects id="surrounding-effects">
|
47
|
+
<effect id="walls-fx">
|
48
|
+
<profile_COMMON>
|
49
|
+
<technique>
|
50
|
+
<phong>
|
51
|
+
<emission>
|
52
|
+
<color>0.05 0.05 0.05 1</color>
|
53
|
+
</emission>
|
54
|
+
<ambient>
|
55
|
+
<color>0.15 0.15 0.15 1</color>
|
56
|
+
</ambient>
|
57
|
+
<diffuse>
|
58
|
+
<color>0.9 0.9 0.9 1</color>
|
59
|
+
</diffuse>
|
60
|
+
<specular>
|
61
|
+
<color>0 0 0 1</color>
|
62
|
+
</specular>
|
63
|
+
<shininess>
|
64
|
+
<float>0.0</float>
|
65
|
+
</shininess>
|
66
|
+
<reflective>
|
67
|
+
<color>1 1 1 1</color>
|
68
|
+
</reflective>
|
69
|
+
<reflectivity>
|
70
|
+
<float>0.0</float>
|
71
|
+
</reflectivity>
|
72
|
+
<transparent>
|
73
|
+
<color>1 1 1 1</color>
|
74
|
+
</transparent>
|
75
|
+
<transparency>
|
76
|
+
<float>0.0</float>
|
77
|
+
</transparency>
|
78
|
+
</phong>
|
79
|
+
</technique>
|
80
|
+
</profile_COMMON>
|
81
|
+
</effect>
|
82
|
+
<effect id="windows-fx">
|
83
|
+
<profile_COMMON>
|
84
|
+
<technique>
|
85
|
+
<phong>
|
86
|
+
<emission>
|
87
|
+
<color>0.0 0.0 0.0 1</color>
|
88
|
+
</emission>
|
89
|
+
<ambient>
|
90
|
+
<color>0.15 0.15 0.15 1</color>
|
91
|
+
</ambient>
|
92
|
+
<diffuse>
|
93
|
+
<color>0.9 0.9 1.0 1</color>
|
94
|
+
</diffuse>
|
95
|
+
<specular>
|
96
|
+
<color>0 0 0 1</color>
|
97
|
+
</specular>
|
98
|
+
<shininess>
|
99
|
+
<float>0.0</float>
|
100
|
+
</shininess>
|
101
|
+
<reflective>
|
102
|
+
<color>1 1 1 1</color>
|
103
|
+
</reflective>
|
104
|
+
<reflectivity>
|
105
|
+
<float>0.2</float>
|
106
|
+
</reflectivity>
|
107
|
+
<transparent>
|
108
|
+
<color>1 1 1 1</color>
|
109
|
+
</transparent>
|
110
|
+
<transparency>
|
111
|
+
<float>0.9</float>
|
112
|
+
</transparency>
|
113
|
+
</phong>
|
114
|
+
</technique>
|
115
|
+
</profile_COMMON>
|
116
|
+
</effect>
|
117
|
+
<% @areas.each do |area_mesh|; id = area_mesh.data[:id].to_s %>
|
118
|
+
<effect id="area_<%= id %>-fx" name="<%= area_mesh.data[:name] %>">
|
119
|
+
<% if area_mesh.data[:texture] %>
|
120
|
+
<extra>
|
121
|
+
<technique sid="sunflow">
|
122
|
+
<diffuse><%= area_mesh.data[:color].join(' ') %></diffuse>
|
123
|
+
</technique>
|
124
|
+
</extra>
|
125
|
+
<% end %>
|
126
|
+
<profile_COMMON>
|
127
|
+
<% if area_mesh.data[:texture] %>
|
128
|
+
<newparam sid="area_<%= id %>-surface">
|
129
|
+
<surface type="2D">
|
130
|
+
<init_from>area_<%= id %>-image</init_from>
|
131
|
+
</surface>
|
132
|
+
</newparam>
|
133
|
+
<newparam sid="area_<%= id %>-sampler">
|
134
|
+
<sampler2D>
|
135
|
+
<source>area_<%= id %>-surface</source>
|
136
|
+
</sampler2D>
|
137
|
+
</newparam>
|
138
|
+
<% end %>
|
139
|
+
<technique>
|
140
|
+
<phong>
|
141
|
+
<emission>
|
142
|
+
<color>0.05 0.05 0.05 1</color>
|
143
|
+
</emission>
|
144
|
+
<ambient>
|
145
|
+
<color>0.1 0.1 0.1 1</color>
|
146
|
+
</ambient>
|
147
|
+
<diffuse>
|
148
|
+
<% if area_mesh.data[:texture] %>
|
149
|
+
<texture texture="area_<%= id %>-sampler"/>
|
150
|
+
<% else %>
|
151
|
+
<color><%= area_mesh.data[:color].join(' ') %> 1</color>
|
152
|
+
<% end %>
|
153
|
+
</diffuse>
|
154
|
+
<specular>
|
155
|
+
<color>0 0 0 1</color>
|
156
|
+
</specular>
|
157
|
+
<shininess>
|
158
|
+
<float>0.0</float>
|
159
|
+
</shininess>
|
160
|
+
<reflective>
|
161
|
+
<color>1 1 1 1</color>
|
162
|
+
</reflective>
|
163
|
+
<reflectivity>
|
164
|
+
<float>0.0</float>
|
165
|
+
</reflectivity>
|
166
|
+
<transparent>
|
167
|
+
<color>1 1 1 1</color>
|
168
|
+
</transparent>
|
169
|
+
<transparency>
|
170
|
+
<float>0.0</float>
|
171
|
+
</transparency>
|
172
|
+
</phong>
|
173
|
+
</technique>
|
174
|
+
</profile_COMMON>
|
175
|
+
</effect>
|
176
|
+
<% end %>
|
177
|
+
<% unless @xrefs; @assets.each_value do |asset| %>
|
178
|
+
<% asset.library_effects.each do |effects| %>
|
179
|
+
<%= effects.to_s %>
|
180
|
+
<% end %>
|
181
|
+
<% end; end %>
|
182
|
+
</library_effects>
|
183
|
+
|
184
|
+
<library_images>
|
185
|
+
<% @areas.each do |area_mesh|; if area_mesh.data[:texture] %>
|
186
|
+
<image id="area_<%= area_mesh.data[:id] %>-image" name="<%= area_mesh.data[:name] %>">
|
187
|
+
<init_from><%= Floorplanner.config['area_textures_path'] +
|
188
|
+
area_mesh.data[:texture].gsub('textures/2d/','').gsub(/\.swf$/,'.png') %></init_from>
|
189
|
+
</image>
|
190
|
+
<% end; end %>
|
191
|
+
|
192
|
+
<% unless @xrefs; @assets.each_value do |asset| %>
|
193
|
+
<% asset.library_images.each do |image| %>
|
194
|
+
<%= image.to_s %>
|
195
|
+
<% end %>
|
196
|
+
<% end; end %>
|
197
|
+
</library_images>
|
198
|
+
|
199
|
+
<library_geometries id="surrounding-geometry">
|
200
|
+
|
201
|
+
<geometry id="walls-geom" name="WallsGeometry">
|
202
|
+
<mesh>
|
203
|
+
<source id="walls-positions" name="position">
|
204
|
+
<float_array id="walls-positions-array" count="<%= @walls.vertices.length*3 %>">
|
205
|
+
<%= @walls.vertices.collect {|v| v.to_floats }.join(' ') %>
|
206
|
+
</float_array>
|
207
|
+
|
208
|
+
<technique_common>
|
209
|
+
<accessor count="<%= @walls.vertices.length %>" offset="0" source="#walls-positions-array" stride="3">
|
210
|
+
<param name="X" type="float"></param>
|
211
|
+
<param name="Y" type="float"></param>
|
212
|
+
<param name="Z" type="float"></param>
|
213
|
+
</accessor>
|
214
|
+
</technique_common>
|
215
|
+
</source>
|
216
|
+
|
217
|
+
<vertices id="walls-vertices">
|
218
|
+
<input semantic="POSITION" source="#walls-positions"/>
|
219
|
+
</vertices>
|
220
|
+
|
221
|
+
<triangles count="<%= @walls.faces.length %>" material="Walls">
|
222
|
+
<input semantic="VERTEX" source="#walls-vertices" offset="0"/>
|
223
|
+
<p>
|
224
|
+
<%= @walls.faces.collect{|f| f.vertices.collect{|v| @walls.vertices.index(v)}}.flatten.join(' ') %>
|
225
|
+
</p>
|
226
|
+
</triangles>
|
227
|
+
</mesh>
|
228
|
+
</geometry>
|
229
|
+
|
230
|
+
<geometry id="windows-geom" name="WindowsGeometry">
|
231
|
+
<%
|
232
|
+
windows_vertices = @walls.windows.collect {|w| w.vertices}.flatten
|
233
|
+
windows_faces = @walls.windows.collect {|w| w.faces}.flatten
|
234
|
+
%>
|
235
|
+
<mesh>
|
236
|
+
<source id="windows-positions" name="position">
|
237
|
+
<float_array id="windows-positions-array" count="<%= @walls.vertices.length*3 %>">
|
238
|
+
<%= windows_vertices.collect {|v| v.to_floats }.join(' ') %>
|
239
|
+
</float_array>
|
240
|
+
|
241
|
+
<technique_common>
|
242
|
+
<accessor count="<%= windows_vertices.length %>" offset="0" source="#windows-positions-array" stride="3">
|
243
|
+
<param name="X" type="float"></param>
|
244
|
+
<param name="Y" type="float"></param>
|
245
|
+
<param name="Z" type="float"></param>
|
246
|
+
</accessor>
|
247
|
+
</technique_common>
|
248
|
+
</source>
|
249
|
+
|
250
|
+
<vertices id="windows-vertices">
|
251
|
+
<input semantic="POSITION" source="#windows-positions"/>
|
252
|
+
</vertices>
|
253
|
+
|
254
|
+
<triangles count="<%= windows_faces.length %>" material="Window">
|
255
|
+
<input semantic="VERTEX" source="#windows-vertices" offset="0"/>
|
256
|
+
<p>
|
257
|
+
<% offset = 0
|
258
|
+
@walls.windows.each do |w|
|
259
|
+
%>
|
260
|
+
<%= w.faces.collect{|f| f.vertices.collect{|v| w.vertices.index(v) + offset}}.flatten.join(' ') %>
|
261
|
+
<% offset += w.vertices.length ; end %>
|
262
|
+
</p>
|
263
|
+
</triangles>
|
264
|
+
</mesh>
|
265
|
+
</geometry>
|
266
|
+
<% @areas.each do |area_mesh|; id = area_mesh.data[:id] %>
|
267
|
+
<geometry id="area_<%= id %>-geom" name="Area_<%= id %>_<%= area_mesh.data[:name] %>-Geometry">
|
268
|
+
<mesh>
|
269
|
+
<source id="area_<%= id %>-positions" name="position">
|
270
|
+
|
271
|
+
<float_array id="area_<%= id %>-positions-array" count="<%= area_mesh.vertices.length*3 %>">
|
272
|
+
<%= area_mesh.vertices.collect {|v| v.to_floats }.join(' ') %>
|
273
|
+
</float_array>
|
274
|
+
|
275
|
+
<technique_common>
|
276
|
+
<accessor count="<%= area_mesh.vertices.length %>" offset="0" source="#area_<%= id %>-positions-array" stride="3">
|
277
|
+
<param name="X" type="float"></param>
|
278
|
+
<param name="Y" type="float"></param>
|
279
|
+
<param name="Z" type="float"></param>
|
280
|
+
</accessor>
|
281
|
+
</technique_common>
|
282
|
+
</source>
|
283
|
+
|
284
|
+
<source id="area_<%= id %>-uvs" name="texcoord">
|
285
|
+
<float_array id="area_<%= id %>-uvs-array" count="<%= area_mesh.texcoord.length %>">
|
286
|
+
<%= area_mesh.texcoord.map{|n| [n.u,n.v]}.flatten.join(' ') %>
|
287
|
+
</float_array>
|
288
|
+
<technique_common>
|
289
|
+
<accessor count="44" source="#area_<%= id %>-uvs-array" stride="2">
|
290
|
+
<param name="S" type="float"/>
|
291
|
+
<param name="T" type="float"/>
|
292
|
+
</accessor>
|
293
|
+
</technique_common>
|
294
|
+
</source>
|
295
|
+
|
296
|
+
<vertices id="area_<%= id %>-vertices">
|
297
|
+
<input semantic="POSITION" source="#area_<%= id %>-positions"/>
|
298
|
+
</vertices>
|
299
|
+
|
300
|
+
<triangles count="<%= area_mesh.faces.length %>" material="<%= "Area_"+id %>">
|
301
|
+
<input semantic="VERTEX" source="#area_<%= id %>-vertices" offset="0"/>
|
302
|
+
<input semantic="TEXCOORD" source="#area_<%= id %>-uvs" offset="1"/>
|
303
|
+
<p>
|
304
|
+
<%=
|
305
|
+
area_mesh.faces.collect { |f|
|
306
|
+
v = f.vertices.collect { |v| area_mesh.vertices.index(v) }
|
307
|
+
t = f.texcoord.collect { |t| area_mesh.texcoord.index(t) }
|
308
|
+
[v[0],t[0],v[1],t[1],v[2],t[2]]
|
309
|
+
}.flatten.join(' ')
|
310
|
+
%>
|
311
|
+
</p>
|
312
|
+
</triangles>
|
313
|
+
</mesh>
|
314
|
+
</geometry>
|
315
|
+
<% end %>
|
316
|
+
<% unless @xrefs; @assets.each_value do |asset| %>
|
317
|
+
<% asset.library_geometries.each do |geometries| %>
|
318
|
+
<%= geometries.to_s %>
|
319
|
+
<% end %>
|
320
|
+
<% end; end %>
|
321
|
+
</library_geometries>
|
322
|
+
<% unless @xrefs %>
|
323
|
+
<library_nodes>
|
324
|
+
<% @assets.each_value do |asset| %>
|
325
|
+
<% asset.library_nodes.each do |nodes| %>
|
326
|
+
<%= nodes.to_s %>
|
327
|
+
<% end %>
|
328
|
+
<% end %>
|
329
|
+
</library_nodes>
|
330
|
+
<% end %>
|
331
|
+
<library_visual_scenes>
|
332
|
+
<visual_scene id="VisualSceneNode" name="<%= @name %>">
|
333
|
+
<extra>
|
334
|
+
<technique sid="sunflow">
|
335
|
+
<image>
|
336
|
+
<resolution>800 600</resolution>
|
337
|
+
<aa>0 2</aa>
|
338
|
+
<filter>gaussian</filter>
|
339
|
+
<sampler>ipr</sampler>
|
340
|
+
</image>
|
341
|
+
<trace_depths>
|
342
|
+
<diffuse>4</diffuse>
|
343
|
+
<reflection>2</reflection>
|
344
|
+
</trace_depths>
|
345
|
+
<gi>
|
346
|
+
<type>ambocc</type>
|
347
|
+
<bright>1 1 1</bright>
|
348
|
+
<dark>0 0 0</dark>
|
349
|
+
<samples>64</samples>
|
350
|
+
<maxdist>3.0 </maxdist>
|
351
|
+
</gi>
|
352
|
+
<sunsky>
|
353
|
+
<up>0 0 1</up>
|
354
|
+
<east>1 0 0</east>
|
355
|
+
<sundir>0.2 0.4 0.7</sundir>
|
356
|
+
<ground>1 1 1</ground>
|
357
|
+
</sunsky>
|
358
|
+
</technique>
|
359
|
+
</extra>
|
360
|
+
<node id="Camera" name="Camera">
|
361
|
+
<lookat>
|
362
|
+
9.0 -1.0 1.4
|
363
|
+
8.0 -2.0 1.4
|
364
|
+
0.0 0.0 1.0
|
365
|
+
</lookat>
|
366
|
+
<instance_camera url="#main-cam"/>
|
367
|
+
</node>
|
368
|
+
<node id="Walls" name="Walls">
|
369
|
+
<instance_geometry url="#walls-geom">
|
370
|
+
<bind_material>
|
371
|
+
<technique_common>
|
372
|
+
<instance_material symbol="Walls" target="#walls-material"/>
|
373
|
+
</technique_common>
|
374
|
+
</bind_material>
|
375
|
+
</instance_geometry>
|
376
|
+
</node>
|
377
|
+
<node id="Windows" name="Windows">
|
378
|
+
<instance_geometry url="#windows-geom">
|
379
|
+
<bind_material>
|
380
|
+
<technique_common>
|
381
|
+
<instance_material symbol="Window" target="#windows-material"/>
|
382
|
+
</technique_common>
|
383
|
+
</bind_material>
|
384
|
+
</instance_geometry>
|
385
|
+
</node>
|
386
|
+
<node id="Areas" name="Areas">
|
387
|
+
<% @areas.each do |area_mesh|; id = area_mesh.data[:id] %>
|
388
|
+
<node id="Area_<%= id %>" name="Area_<%= id %>">
|
389
|
+
<instance_geometry url="#area_<%= id %>-geom">
|
390
|
+
<bind_material>
|
391
|
+
<technique_common>
|
392
|
+
<instance_material symbol="Area_<%= id %>" target="#area_<%= id %>-material"/>
|
393
|
+
</technique_common>
|
394
|
+
</bind_material>
|
395
|
+
</instance_geometry>
|
396
|
+
</node>
|
397
|
+
<% if area_mesh.data[:type] == 'generated_area' %>
|
398
|
+
<node id="Area_<%= id %>-cap" name="Area_<%= id %>-cap">
|
399
|
+
<translate>0.0 0.0 <%= @areas.ceiling_z %></translate>
|
400
|
+
<instance_geometry url="#area_<%= id %>-geom">
|
401
|
+
<bind_material>
|
402
|
+
<technique_common>
|
403
|
+
<instance_material symbol="Area_<%= id %>" target="#walls-material"/>
|
404
|
+
</technique_common>
|
405
|
+
</bind_material>
|
406
|
+
</instance_geometry>
|
407
|
+
</node>
|
408
|
+
<% end %>
|
409
|
+
<% end %>
|
410
|
+
</node>
|
411
|
+
<% @elements.each do |element| %>
|
412
|
+
<node name="<%= element[:asset].title %>">
|
413
|
+
<translate><%= element[:position].to_floats %></translate>
|
414
|
+
<% if element[:matrix] %>
|
415
|
+
<matrix><%= element[:matrix].to_a.join ' ' %></matrix>
|
416
|
+
<% end %>
|
417
|
+
<% if element[:rotation].x > 0 %>
|
418
|
+
<rotate sid="rotateX">1 0 0 <%= element[:rotation].x %></rotate>
|
419
|
+
<% end %>
|
420
|
+
<% if element[:rotation].y > 0 %>
|
421
|
+
<rotate sid="rotateY">0 1 0 <%= element[:rotation].y %></rotate>
|
422
|
+
<% end %>
|
423
|
+
<% if element[:rotation].z > 0 %>
|
424
|
+
<rotate sid="rotateZ">0 0 1 <%= element[:rotation].z %></rotate>
|
425
|
+
<% end %>
|
426
|
+
<scale><%= element[:scale].to_floats %></scale>
|
427
|
+
<% if @xrefs %>
|
428
|
+
<instance_node url="<%= element[:asset].dae_path %>"/>
|
429
|
+
<% else %>
|
430
|
+
<%= element[:asset].visual_scene_node.to_s %>
|
431
|
+
<% end %>
|
432
|
+
</node>
|
433
|
+
<% end %>
|
434
|
+
</visual_scene>
|
435
|
+
</library_visual_scenes>
|
436
|
+
<scene>
|
437
|
+
<instance_visual_scene url="#VisualSceneNode"/>
|
438
|
+
</scene>
|
439
|
+
</COLLADA>
|