fml 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.gitignore +8 -0
  2. data/README +1 -0
  3. data/Rakefile +3 -0
  4. data/bin/fml2dae.rb +15 -0
  5. data/bin/fml2obj.rb +10 -0
  6. data/fml.gemspec +36 -0
  7. data/lib/collada/document.rb +101 -0
  8. data/lib/collada/geometry.rb +110 -0
  9. data/lib/config.yml +17 -0
  10. data/lib/floorplanner/area_builder.rb +42 -0
  11. data/lib/floorplanner/asset.rb +185 -0
  12. data/lib/floorplanner/collada_export.rb +118 -0
  13. data/lib/floorplanner/design.rb +108 -0
  14. data/lib/floorplanner/document.rb +68 -0
  15. data/lib/floorplanner/obj_export.rb +24 -0
  16. data/lib/floorplanner/opening3d.rb +140 -0
  17. data/lib/floorplanner/rib_export.rb +24 -0
  18. data/lib/floorplanner/svg_export.rb +25 -0
  19. data/lib/floorplanner/wall3d.rb +97 -0
  20. data/lib/floorplanner/wall_builder.rb +165 -0
  21. data/lib/floorplanner.rb +52 -0
  22. data/lib/geom/connection.rb +14 -0
  23. data/lib/geom/ear_trim.rb +52 -0
  24. data/lib/geom/edge.rb +89 -0
  25. data/lib/geom/glu_tess.rb +34 -0
  26. data/lib/geom/intersection.rb +38 -0
  27. data/lib/geom/matrix3d.rb +141 -0
  28. data/lib/geom/number.rb +104 -0
  29. data/lib/geom/plane.rb +36 -0
  30. data/lib/geom/polygon.rb +264 -0
  31. data/lib/geom/triangle.rb +38 -0
  32. data/lib/geom/triangle_mesh.rb +94 -0
  33. data/lib/geom/vertex.rb +33 -0
  34. data/lib/geom.rb +13 -0
  35. data/lib/keyhole/archive.rb +36 -0
  36. data/tasks/github-gem.rake +315 -0
  37. data/views/design.dae.erb +439 -0
  38. data/views/design.obj.erb +17 -0
  39. data/views/design.rib.erb +17 -0
  40. data/views/design.svg.erb +42 -0
  41. data/xml/collada_schema_1_4.xsd +11046 -0
  42. data/xml/fml.rng +268 -0
  43. data/xml/fml2kml.xsl +59 -0
  44. metadata +117 -0
@@ -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 &lt;johnny@floorplanner.com&gt;</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
+ </perspective>
20
+ </technique_common>
21
+ </optics>
22
+ </camera>
23
+ </library_cameras>
24
+
25
+ <library_materials id="surrounding-materials">
26
+ <material id="walls-material" name="WallsMaterial">
27
+ <instance_effect url="#walls-fx"/>
28
+ </material>
29
+ <material id="windows-material" name="WindowsMaterial">
30
+ <instance_effect url="#windows-fx"/>
31
+ </material>
32
+ <% @areas.each do |area_mesh| %>
33
+ <material id="area_<%= area_mesh.data[:id] %>-material" name="<%= area_mesh.data[:name] %>">
34
+ <instance_effect url="#area_<%= area_mesh.data[:id] %>-fx"/>
35
+ </material>
36
+ <% end %>
37
+ <% unless @xrefs; @assets.each_value do |asset| %>
38
+ <% asset.library_materials.each do |materials| %>
39
+ <%= materials.to_s %>
40
+ <% end %>
41
+ <% end; end %>
42
+ </library_materials>
43
+
44
+ <library_effects id="surrounding-effects">
45
+ <effect id="walls-fx">
46
+ <profile_COMMON>
47
+ <technique>
48
+ <phong>
49
+ <emission>
50
+ <color>0.05 0.05 0.05 1</color>
51
+ </emission>
52
+ <ambient>
53
+ <color>0.15 0.15 0.15 1</color>
54
+ </ambient>
55
+ <diffuse>
56
+ <color>0.9 0.9 0.9 1</color>
57
+ </diffuse>
58
+ <specular>
59
+ <color>0 0 0 1</color>
60
+ </specular>
61
+ <shininess>
62
+ <float>0.0</float>
63
+ </shininess>
64
+ <reflective>
65
+ <color>1 1 1 1</color>
66
+ </reflective>
67
+ <reflectivity>
68
+ <float>0.0</float>
69
+ </reflectivity>
70
+ <transparent>
71
+ <color>1 1 1 1</color>
72
+ </transparent>
73
+ <transparency>
74
+ <float>0.0</float>
75
+ </transparency>
76
+ </phong>
77
+ </technique>
78
+ </profile_COMMON>
79
+ </effect>
80
+ <effect id="windows-fx">
81
+ <profile_COMMON>
82
+ <technique>
83
+ <phong>
84
+ <emission>
85
+ <color>0.0 0.0 0.0 1</color>
86
+ </emission>
87
+ <ambient>
88
+ <color>0.15 0.15 0.15 1</color>
89
+ </ambient>
90
+ <diffuse>
91
+ <color>0.9 0.9 1.0 1</color>
92
+ </diffuse>
93
+ <specular>
94
+ <color>0 0 0 1</color>
95
+ </specular>
96
+ <shininess>
97
+ <float>0.0</float>
98
+ </shininess>
99
+ <reflective>
100
+ <color>1 1 1 1</color>
101
+ </reflective>
102
+ <reflectivity>
103
+ <float>0.2</float>
104
+ </reflectivity>
105
+ <transparent>
106
+ <color>1 1 1 1</color>
107
+ </transparent>
108
+ <transparency>
109
+ <float>0.9</float>
110
+ </transparency>
111
+ </phong>
112
+ </technique>
113
+ </profile_COMMON>
114
+ </effect>
115
+ <% @areas.each do |area_mesh|; id = area_mesh.data[:id].to_s %>
116
+ <effect id="area_<%= id %>-fx" name="<%= area_mesh.data[:name] %>">
117
+ <% if area_mesh.data[:texture] %>
118
+ <extra>
119
+ <technique sid="sunflow">
120
+ <diffuse><%= area_mesh.data[:color].join(' ') %></diffuse>
121
+ </technique>
122
+ </extra>
123
+ <% end %>
124
+ <profile_COMMON>
125
+ <% if area_mesh.data[:texture] %>
126
+ <newparam sid="area_<%= id %>-surface">
127
+ <surface type="2D">
128
+ <init_from>area_<%= id %>-image</init_from>
129
+ </surface>
130
+ </newparam>
131
+ <newparam sid="area_<%= id %>-sampler">
132
+ <sampler2D>
133
+ <source>area_<%= id %>-surface</source>
134
+ </sampler2D>
135
+ </newparam>
136
+ <% end %>
137
+ <technique>
138
+ <phong>
139
+ <emission>
140
+ <color>0.05 0.05 0.05 1</color>
141
+ </emission>
142
+ <ambient>
143
+ <color>0.1 0.1 0.1 1</color>
144
+ </ambient>
145
+ <diffuse>
146
+ <% if area_mesh.data[:texture] %>
147
+ <texture texture="area_<%= id %>-sampler"/>
148
+ <% else %>
149
+ <color><%= area_mesh.data[:color].join(' ') %> 1</color>
150
+ <% end %>
151
+ </diffuse>
152
+ <specular>
153
+ <color>0 0 0 1</color>
154
+ </specular>
155
+ <shininess>
156
+ <float>0.0</float>
157
+ </shininess>
158
+ <reflective>
159
+ <color>1 1 1 1</color>
160
+ </reflective>
161
+ <reflectivity>
162
+ <float>0.0</float>
163
+ </reflectivity>
164
+ <transparent>
165
+ <color>1 1 1 1</color>
166
+ </transparent>
167
+ <transparency>
168
+ <float>0.0</float>
169
+ </transparency>
170
+ </phong>
171
+ </technique>
172
+ </profile_COMMON>
173
+ </effect>
174
+ <% end %>
175
+ <% unless @xrefs; @assets.each_value do |asset| %>
176
+ <% asset.library_effects.each do |effects| %>
177
+ <%= effects.to_s %>
178
+ <% end %>
179
+ <% end; end %>
180
+ </library_effects>
181
+
182
+ <library_images>
183
+ <% @areas.each do |area_mesh|; if area_mesh.data[:texture] %>
184
+ <image id="area_<%= area_mesh.data[:id] %>-image" name="<%= area_mesh.data[:name] %>">
185
+ <init_from><%= Floorplanner.config['area_textures_path'] +
186
+ area_mesh.data[:texture].gsub('textures/2d/','').gsub(/\.swf$/,'.png') %></init_from>
187
+ </image>
188
+ <% end; end %>
189
+
190
+ <% unless @xrefs; @assets.each_value do |asset| %>
191
+ <% asset.library_images.each do |image| %>
192
+ <%= image.to_s %>
193
+ <% end %>
194
+ <% end; end %>
195
+ </library_images>
196
+
197
+ <library_geometries id="surrounding-geometry">
198
+
199
+ <geometry id="walls-geom" name="WallsGeometry">
200
+ <mesh>
201
+ <source id="walls-positions" name="position">
202
+ <float_array id="walls-positions-array" count="<%= @walls.vertices.length*3 %>">
203
+ <%= @walls.vertices.collect {|v| v.to_floats }.join(' ') %>
204
+ </float_array>
205
+
206
+ <technique_common>
207
+ <accessor count="<%= @walls.vertices.length %>" offset="0" source="#walls-positions-array" stride="3">
208
+ <param name="X" type="float"></param>
209
+ <param name="Y" type="float"></param>
210
+ <param name="Z" type="float"></param>
211
+ </accessor>
212
+ </technique_common>
213
+ </source>
214
+
215
+ <vertices id="walls-vertices">
216
+ <input semantic="POSITION" source="#walls-positions"/>
217
+ </vertices>
218
+
219
+ <triangles count="<%= @walls.faces.length %>" material="Walls">
220
+ <input semantic="VERTEX" source="#walls-vertices" offset="0"/>
221
+ <p>
222
+ <%= @walls.faces.collect{|f| f.vertices.collect{|v| @walls.vertices.index(v)}}.flatten.join(' ') %>
223
+ </p>
224
+ </triangles>
225
+ </mesh>
226
+ </geometry>
227
+
228
+ <geometry id="windows-geom" name="WindowsGeometry">
229
+ <%
230
+ windows_vertices = @walls.windows.collect {|w| w.vertices}.flatten
231
+ windows_faces = @walls.windows.collect {|w| w.faces}.flatten
232
+ %>
233
+ <mesh>
234
+ <source id="windows-positions" name="position">
235
+ <float_array id="windows-positions-array" count="<%= @walls.vertices.length*3 %>">
236
+ <%= windows_vertices.collect {|v| v.to_floats }.join(' ') %>
237
+ </float_array>
238
+
239
+ <technique_common>
240
+ <accessor count="<%= windows_vertices.length %>" offset="0" source="#windows-positions-array" stride="3">
241
+ <param name="X" type="float"></param>
242
+ <param name="Y" type="float"></param>
243
+ <param name="Z" type="float"></param>
244
+ </accessor>
245
+ </technique_common>
246
+ </source>
247
+
248
+ <vertices id="windows-vertices">
249
+ <input semantic="POSITION" source="#windows-positions"/>
250
+ </vertices>
251
+
252
+ <triangles count="<%= windows_faces.length %>" material="Window">
253
+ <input semantic="VERTEX" source="#windows-vertices" offset="0"/>
254
+ <p>
255
+ <% offset = 0
256
+ @walls.windows.each do |w|
257
+ %>
258
+ <%= w.faces.collect{|f| f.vertices.collect{|v| w.vertices.index(v) + offset}}.flatten.join(' ') %>
259
+ <% offset += w.vertices.length ; end %>
260
+ </p>
261
+ </triangles>
262
+ </mesh>
263
+ </geometry>
264
+ <% @areas.each do |area_mesh|; id = area_mesh.data[:id] %>
265
+ <geometry id="area_<%= id %>-geom" name="Area_<%= id %>_<%= area_mesh.data[:name] %>-Geometry">
266
+ <mesh>
267
+ <source id="area_<%= id %>-positions" name="position">
268
+
269
+ <float_array id="area_<%= id %>-positions-array" count="<%= area_mesh.vertices.length*3 %>">
270
+ <%= area_mesh.vertices.collect {|v| v.to_floats }.join(' ') %>
271
+ </float_array>
272
+
273
+ <technique_common>
274
+ <accessor count="<%= area_mesh.vertices.length %>" offset="0" source="#area_<%= id %>-positions-array" stride="3">
275
+ <param name="X" type="float"></param>
276
+ <param name="Y" type="float"></param>
277
+ <param name="Z" type="float"></param>
278
+ </accessor>
279
+ </technique_common>
280
+ </source>
281
+
282
+ <source id="area_<%= id %>-uvs" name="texcoord">
283
+ <float_array id="area_<%= id %>-uvs-array" count="<%= area_mesh.texcoord.length %>">
284
+ <%= area_mesh.texcoord.map{|n| [n.u,n.v]}.flatten.join(' ') %>
285
+ </float_array>
286
+ <technique_common>
287
+ <accessor count="44" source="#area_<%= id %>-uvs-array" stride="2">
288
+ <param name="S" type="float"/>
289
+ <param name="T" type="float"/>
290
+ </accessor>
291
+ </technique_common>
292
+ </source>
293
+
294
+ <vertices id="area_<%= id %>-vertices">
295
+ <input semantic="POSITION" source="#area_<%= id %>-positions"/>
296
+ </vertices>
297
+
298
+ <triangles count="<%= area_mesh.faces.length %>" material="<%= "Area_"+id %>">
299
+ <input semantic="VERTEX" source="#area_<%= id %>-vertices" offset="0"/>
300
+ <input semantic="TEXCOORD" source="#area_<%= id %>-uvs" offset="1"/>
301
+ <p>
302
+ <%=
303
+ area_mesh.faces.collect { |f|
304
+ v = f.vertices.collect { |v| area_mesh.vertices.index(v) }
305
+ t = f.texcoord.collect { |t| area_mesh.texcoord.index(t) }
306
+ [v[0],t[0],v[1],t[1],v[2],t[2]]
307
+ }.flatten.join(' ')
308
+ %>
309
+ </p>
310
+ </triangles>
311
+ </mesh>
312
+ </geometry>
313
+ <% end %>
314
+ <% unless @xrefs; @assets.each_value do |asset| %>
315
+ <% asset.library_geometries.each do |geometries| %>
316
+ <%= geometries.to_s %>
317
+ <% end %>
318
+ <% end; end %>
319
+ </library_geometries>
320
+ <% unless @xrefs %>
321
+ <library_nodes>
322
+ <% @assets.each_value do |asset| %>
323
+ <% asset.library_nodes.each do |nodes| %>
324
+ <%= nodes.to_s %>
325
+ <% end %>
326
+ <% end %>
327
+ </library_nodes>
328
+ <% end %>
329
+ <library_visual_scenes>
330
+ <visual_scene id="VisualSceneNode" name="<%= @name %>">
331
+ <extra>
332
+ <technique sid="sunflow">
333
+ <image>
334
+ <resolution>800 600</resolution>
335
+ <aa>0 2</aa>
336
+ <filter>gaussian</filter>
337
+ </image>
338
+ <trace_depths>
339
+ <diffuse>4</diffuse>
340
+ <reflection>2</reflection>
341
+ </trace_depths>
342
+ <gi>
343
+ <type>ambocc</type>
344
+ <bright>1 1 1</bright>
345
+ <dark>0 0 0</dark>
346
+ <samples>64</samples>
347
+ <maxdist>3.0 </maxdist>
348
+ </gi>
349
+ <background>
350
+ <color>1.0 1.0 1.0</color>
351
+ </background>
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>
@@ -0,0 +1,17 @@
1
+ # Floorplanner.com
2
+ # <%= @name %>
3
+ <%
4
+ vertices = @walls.vertices + @areas.vertices
5
+ faces = @walls.faces + @areas.faces
6
+ %>
7
+ <% vertices.each do |v| %>
8
+ v <%= [v.x,v.z,v.y].join(' ') %><% end %>
9
+ <%
10
+ faces.each do |f|
11
+ v = [
12
+ vertices.index(f.vertices[0]),
13
+ vertices.index(f.vertices[1]),
14
+ vertices.index(f.vertices[2])
15
+ ]
16
+ if v.compact.length == 3 %>
17
+ f <%= v.collect{|w|w+1}.join(' ') %><% end ; end %>
@@ -0,0 +1,17 @@
1
+ Display "design.tif" "file" "rgb"
2
+ Format 480 320 -1
3
+ Projection "perspective" "fov" 45
4
+ Translate -5 -2 22
5
+ Rotate 240 1 0 0
6
+ Rotate -40 0 0 1
7
+ WorldBegin
8
+   LightSource "ambientlight" 1 "intensity" 1.0
9
+   LightSource "distantlight" 2 "from" [0 0 4] "to" [0 0 0] "intensity" 5.0
10
+   Color [ 0.95 0.95 0.95 ]
11
+ <% @walls.faces.each do |face| %>
12
+   Polygon "P" [ <%= face.vertices.collect{|v| [v.x,v.y,v.z]}.flatten.join(' ') %> ]
13
+ <% end %>
14
+ <% @areas.faces.each do |face| %>
15
+   Polygon "P" [ <%= face.vertices.collect{|v| [v.x,v.y,v.z]}.flatten.join(' ') %> ]
16
+ <% end %>
17
+ WorldEnd
@@ -0,0 +1,42 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <svg
3
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
4
+ xmlns:cc="http://creativecommons.org/ns#"
5
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6
+ xmlns:svg="http://www.w3.org/2000/svg"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ width="<%= Floorplanner.config['svg']['width'] %>px"
9
+ height="<%= Floorplanner.config['svg']['height'] %>px"
10
+ version="1.1"
11
+ id="svg2">
12
+
13
+ <metadata id="metadata39">
14
+ <rdf:RDF>
15
+ <cc:Work
16
+ rdf:about="">
17
+ <dc:format>image/svg+xml</dc:format>
18
+ <dc:type
19
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
20
+ <dc:title><%= @name %></dc:title>
21
+ <dc:creator>
22
+ <cc:Agent>
23
+ <dc:title><%= @author %></dc:title>
24
+ </cc:Agent>
25
+ </dc:creator>
26
+ <dc:publisher>
27
+ <cc:Agent>
28
+ <dc:title>Floorplanner.com</dc:title>
29
+ </cc:Agent>
30
+ </dc:publisher>
31
+ </cc:Work>
32
+ </rdf:RDF>
33
+ </metadata>
34
+ <g id="areas"><%
35
+ @areas.each do |area| %>
36
+ <polygon points="<%= area.vertices.collect{|v| [(v.x+mod_x)*ratio,(v.y+mod_y)*ratio].join(',')}.join(' ') %>" style="fill:<%= area.data[:color] %>;stroke-width:1;stroke:rgb(100,100,100);stroke-linejoin:round;stroke-dasharray:1, 1;stroke-dashoffset:0"/><% end %>
37
+ </g>
38
+ <g id="walls"><%
39
+ @walls.each do |wall| %>
40
+ <polygon points="<%= wall.outline.vertices.collect{|v| [(v.x+mod_x)*ratio,(v.y+mod_y)*ratio].join(',')}.join(' ') %>" style="fill:<%= wall.data[:color] %>;stroke-width:1;stroke:rgb(0,0,0);stroke-linejoin:round"/><% end %>
41
+ </g>
42
+ </svg>