1// Persistence Of Vision Ray Tracer Include File
2// ---------------------------------------------
3// File: @(#)mechsim.inc
4// Description: mechanics simulation include file - version 0.4
5// Features demonstrated: mechsim
6// Creation Date: $ August 2002 $
7// Last modified: $ 27 May 2005, 16:34:33 $
8// Author: Christoph Hormann <chris_hormann@gmx.de>
9//
10// This include file is part of the MechSim patch in MegaPOV
11// Like the patch it is subject to the conditions in povlegal.doc
12// that comes with MegaPOV No part of it may be used outside POV-Ray
13// without permission
14//
15
16#ifdef(MECHSIM_Inc_Temp)
17// do nothing
18#else
19#declare MECHSIM_Inc_Temp = version;
20
21#ifdef(View_POV_Include_Stack)
22#   debug "including mechsim.inc\n"
23#end
24
25#version unofficial megapov 1.2;
26
27#include "math.inc"
28#include "transforms.inc"
29
30// #######################################################################################
31//   constants
32// #######################################################################################
33
34#declare MSIM_INCLUDE_VERSION=0.4;
35
36#declare MECHSIM_METHOD_EULER=1;
37#declare MECHSIM_METHOD_HEUN=2;
38#declare MECHSIM_METHOD_RUNGE_KUTTA4=3;
39#declare MECHSIM_METHOD_GRADIENT=4;
40
41#declare MECHSIM_COLLISION_NONE=0;
42#declare MECHSIM_COLLISION_ALL=1;
43#declare MECHSIM_COLLISION_GROUP=2;
44
45#declare MECHSIM_ENV_METHOD_FORCE=1;
46#declare MECHSIM_ENV_METHOD_IMPACT=2;
47
48#declare MECHSIM_COLLISION_BOUNDING_NO=0;
49#declare MECHSIM_COLLISION_BOUNDING_AUTO=1;
50#declare MECHSIM_COLLISION_BOUNDING_BOX=2;
51#declare MECHSIM_COLLISION_BOUNDING_HASH=3;
52
53#declare No_Trans=transform{}
54
55#declare No_Fixed=function(x, y, z) {-1}
56#declare No_Attach=function(x, y, z) {-1}
57#declare No_Force=function(x, y, z) {-1}
58
59// #######################################################################################
60//   global parameters
61// #######################################################################################
62
63#ifndef (MSim_File_Decimals)
64	#declare MSim_File_Decimals=12;
65#end
66
67#ifndef (MSim_Test_Render)
68	#declare MSim_Test_Render=false;
69#end
70
71#ifndef (MSim_Tex_N)
72	#declare MSim_Tex_N=
73	texture {
74		pigment {
75			color rgb <0.8,0.8,1.0>
76		}
77		finish{
78			diffuse 0.3
79			ambient 0.0
80			specular 0.6
81
82			#if (!MSim_Test_Render)
83				reflection {
84					0.8
85					metallic
86				}
87			#end
88
89			conserve_energy
90		}
91	}
92#end
93
94#ifndef (MSim_Tex_C)
95	#declare MSim_Tex_C=
96	texture {
97		pigment {
98			color rgb <1, 0.5, 0.1>
99		}
100		finish{
101			diffuse 0.3
102			ambient 0.0
103			specular 0.6
104
105			#if (!MSim_Test_Render)
106				reflection {
107					0.8
108					metallic
109				}
110			#end
111
112			conserve_energy
113		}
114	}
115#end
116
117#ifndef (MSim_Tex_Mesh)
118	#declare MSim_Tex_Mesh=
119	texture {
120		pigment {
121			color rgb <0.4, 0.3, 1>
122		}
123		finish{
124			diffuse 0.3
125			ambient 0.0
126			specular 0.6
127
128			#if (!MSim_Test_Render)
129				reflection {
130					0.8
131					metallic
132				}
133			#end
134
135			conserve_energy
136		}
137	}
138#end
139
140#ifndef (fn_Stress_CM)
141	#declare fn_Stress_CM=
142	function {
143		pigment {
144			gradient x
145			color_map {
146				[ 0.00 color rgb<0.450, 0.750, 0.620> ]
147				[ 0.25 color rgb<0.256, 0.430, 1.000> ]
148				[ 0.50 color rgb<0.000, 0.000, 0.441> ]
149				[ 0.75 color rgb<1.000, 0.456, 0.456> ]
150				[ 1.00 color rgb<0.900, 0.800, 0.000> ]
151			}
152		}
153	}
154#end
155
156
157// =======================================================================================
158//  Vector_Function()
159//
160//  generates a pigment function from three float functions
161//  representing the x, y and z directions
162//
163//  Parameters:
164//      Fn_X, Fn_Y, Fn_Z - three user defined functions
165//
166//  The way this macro works makes it necessary to have a limited range for the
167//  function values.  Vector_Function() is a wrapper macro for
168//  Vector_Function_Range() using a default range of 1e6.  If necessary this can be
169//  changed by declaring a different value for MSim_Fn_Range before including
170//  'mechsim.inc'.
171//
172// =======================================================================================
173
174#ifndef (MSim_Fn_Range)
175	#declare MSim_Fn_Range=1e6;
176#end
177
178#macro Vector_Function_Range(Fn_X, Fn_Y, Fn_Z, Range)
179
180	#local PigX=
181	pigment {
182		function { 0.5+Fn_X(x, y, z)*(0.5/Range) }
183		color_map {
184			[0.0 color rgb -3*Range*x ]
185			[0.5 color rgb 0 ]
186			[1.0 color rgb  3*Range*x ]
187		}
188	}
189
190	#local PigY=
191	pigment {
192		function { 0.5+Fn_Y(x, y, z)*(0.5/Range) }
193		color_map {
194			[0.0 color rgb -3*Range*y ]
195			[0.5 color rgb 0 ]
196			[1.0 color rgb  3*Range*y ]
197		}
198	}
199
200	#local PigZ=
201	pigment {
202		function { 0.5+Fn_Z(x, y, z)*(0.5/Range) }
203		color_map {
204			[0.0 color rgb -3*Range*z ]
205			[0.5 color rgb 0 ]
206			[1.0 color rgb  3*Range*z ]
207		}
208	}
209
210	function {
211		pigment {
212			average
213			pigment_map {
214				[1 PigX]
215				[1 PigY]
216				[1 PigZ]
217			}
218		}
219	}
220
221#end
222
223#macro Vector_Function(Fn_X, Fn_Y, Fn_Z)
224
225Vector_Function_Range(
226	function { Fn_X(x, y, z) },
227	function { Fn_Y(x, y, z) },
228	function { Fn_Z(x, y, z) },
229	MSim_Fn_Range
230)
231
232#end
233
234// #######################################################################################
235//   Object diplay macros
236// #######################################################################################
237
238// =======================================================================================
239//  MechSim_Show_Objects_X()
240//
241//  generates objects representing parts of the simulation topology
242//  this variant also shows viscoelastic connections
243//
244//  Parameters:
245//      Start_Mass_Index       - index of the first mass that should be displayed.
246//                               Should be stored when the topology is generated.
247//      Start_Connection_Index - index of the first connection
248//      Start_VE_Index         - index of the first viscoelastic connection
249//      Start_Face_Index       - index of the first face
250//      End_Mass_Index         - index of the last mass that should be displayed.
251//                               if <0 all masses until the last are displayed.
252//      End_Connection_Index   - index of the last connection that should be displayed.
253//                               if <0 all connections until the last are displayed.
254//      End_VE_Index           - index of the last viscoelastic connection that should be displayed.
255//                               if <0 all viscoelastic connections until the last are displayed.
256//      End_Face_Index         - index of the last face that should be displayed.
257//                               if <0 all faces until the last are displayed.
258//      Connect_Rad            - Radius to use for the connections, values <0 lead
259//                               to using  0.4*mass radius.
260//      Show_Faces             - Only generate a mesh from the faces instead of
261//                               cylinders and spheres.
262//      Stress_Fact            - if >0 the connections are textured to visualize
263//                               the stress.  Values are scaled with this factor.
264//      File_Name              - string, if length is >0 the objects are written to a
265//                               file with that name in addition
266//
267// =======================================================================================
268#macro MechSim_Show_Objects_X(Start_Mass_Index, Start_Connection_Index, Start_VE_Index, Start_Face_Index, End_Mass_Index, End_Connection_Index, End_VE_Index, End_Face_Index, Connect_Rad, Show_Faces, Stress_Fact, File_Name)
269
270	object {
271	#if (End_Mass_Index<0)
272		#local End_Mass=mechsim:mass_count;
273	#else
274		#local End_Mass=End_Mass_Index;
275	#end
276
277	#if (End_Connection_Index<0)
278		#local End_Connection=mechsim:connection_count;
279	#else
280		#local End_Connection=End_Connection_Index;
281	#end
282
283	#if (End_VE_Index<0)
284		#local End_VE=mechsim:viscoelastic_count;
285	#else
286		#local End_VE=End_VE_Index;
287	#end
288
289	#if (End_Face_Index<0)
290		#local End_Face=mechsim:face_count;
291	#else
292		#local End_Face=End_Face_Index;
293	#end
294
295	#if (strlen(File_Name)=0)
296		#local Write_File=false;
297		#debug "Generating Objects..."
298	#else
299		#local Write_File=true;
300
301		#fopen FILE File_Name write
302
303		#if (Show_Faces)
304			#write (FILE, "// simulation topology objects (",str(End_Face-Start_Face_Index,0,0)," faces)\n")
305		#else
306			#if (Connect_Rad != 0)
307				#write (FILE, "// simulation topology objects (",str(End_Mass-Start_Mass_Index,0,0)," masses, ",
308				                                                 str(End_VE-Start_VE_Index,0,0)," viscoelastic connections, ",
309				                                                 str(End_Connection-Start_Connection_Index,0,0)," connections)\n")
310			#else
311				#write (FILE, "// simulation topology objects (",str(End_Mass-Start_Mass_Index,0,0)," masses)\n")
312			#end
313		#end
314		#write (FILE, "// written by MechSim include file version ",str(MSIM_INCLUDE_VERSION,1,1),"\n\n")
315
316		#if (Stress_Fact>0)
317			#write (FILE, "#local Fin_Stress=\n")
318			#write (FILE, "  finish {\n")
319			#write (FILE, "    specular 0.3\n")
320			#write (FILE, "    diffuse 0.7\n")
321			#write (FILE, "  }\n\n")
322		#end
323
324		#debug concat("Generating Objects (writing to file ",File_Name,")...")
325
326	#end
327
328	#if (!Show_Faces)
329		#if ((End_Mass>Start_Mass_Index) | (End_Connection>Start_Connection_Index) | (End_VE>Start_VE_Index))
330
331			#if ((End_Mass>Start_Mass_Index) & ((End_Connection>Start_Connection_Index) | (End_VE>Start_VE_Index)))
332				union {
333					#if (Write_File) #write (FILE, "  union {\n") #end
334			#else
335				object {
336					#if (Write_File) #write (FILE, "  object {\n") #end
337			#end
338
339			#if (End_Mass>Start_Mass_Index)
340
341				#if (End_Mass>Start_Mass_Index+1)
342					union {
343						#if (Write_File) #write (FILE, "  union {\n") #end
344				#else
345					object {
346						#if (Write_File) #write (FILE, "  object {\n") #end
347				#end
348
349				#local Cnt=Start_Mass_Index;
350
351				#while (Cnt<End_Mass)
352					sphere {
353						mechsim:mass(Cnt):position,
354	          mechsim:mass(Cnt):radius
355	        }
356
357					#if (Write_File)
358						#write (FILE, "    sphere {<",vstr(3,mechsim:mass(Cnt):position,",",0,MSim_File_Decimals), ">, ",
359							                             str(mechsim:mass(Cnt):radius,0,MSim_File_Decimals), " }\n")
360					#end
361
362					#local Cnt=Cnt+1;
363				#end
364
365						texture { MSim_Tex_N }
366					}
367
368				#if (Write_File)
369					#write (FILE, "    texture { MSim_Tex_N }\n  }\n")
370				#end
371			#end
372
373			#if (End_Connection>Start_Connection_Index)
374
375				#if (Connect_Rad != 0)
376
377					#if (End_Connection>Start_Connection_Index+1)
378						union {
379							#if (Write_File) #write (FILE, "  union {\n") #end
380					#else
381						object {
382							#if (Write_File) #write (FILE, "  object {\n") #end
383					#end
384
385					#local Cnt=Start_Connection_Index;
386
387					#while (Cnt<End_Connection)
388						#local Dist = vlength(mechsim:mass(mechsim:connection(Cnt):index1):position-
389							                    mechsim:mass(mechsim:connection(Cnt):index2):position);
390						#if (Dist>0.0001)
391							cylinder {
392								mechsim:mass(mechsim:connection(Cnt):index1):position,
393								mechsim:mass(mechsim:connection(Cnt):index2):position,
394
395								#if (Write_File)
396									#write (FILE, "    cylinder {<",vstr(3,mechsim:mass(mechsim:connection(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
397										                              vstr(3,mechsim:mass(mechsim:connection(Cnt):index2):position,",",0,MSim_File_Decimals), ">, ")
398								#end
399
400								#if (Connect_Rad<0)
401									#local Radius=mechsim:mass(mechsim:connection(Cnt):index1):radius*0.4;
402								#else
403									#local Radius=Connect_Rad;
404								#end
405
406								Radius
407
408								#if (Write_File)
409									#write (FILE, str(Radius,0,MSim_File_Decimals), " ")
410								#end
411
412								#if (Stress_Fact>0)
413
414									#local Stress=((Dist-mechsim:connection(Cnt):length)/mechsim:connection(Cnt):length)*Stress_Fact + 0.5;
415									#local Stress=max(0.0, min(1.0, Stress));
416									texture {
417										pigment { color fn_Stress_CM(Stress, 0, 0) }
418										finish {
419											specular 0.3
420											diffuse 0.7
421										}
422									}
423
424									#if (Write_File)
425										#write (FILE, "texture{pigment{ color rgb <",vstr(3,fn_Stress_CM(Stress,0,0),",",0,4), "> }finish{Fin_Stress}} ")
426									#end
427
428								#end
429							}
430							#if (Write_File)
431								#write (FILE, "}\n")
432							#end
433
434						#end
435
436						#local Cnt=Cnt+1;
437					#end
438
439					#if (Stress_Fact<=0)
440						  texture { MSim_Tex_C }
441
442						#if (Write_File)
443							#write (FILE, "    texture { MSim_Tex_C }\n")
444						#end
445					#end
446						}
447					#if (Write_File)
448						#write (FILE, "  }\n")
449					#end
450				#end
451			#end
452
453			#if (End_VE>Start_VE_Index)
454
455				#if (Connect_Rad != 0)
456
457					#if (End_VE>Start_VE_Index+1)
458						union {
459							#if (Write_File) #write (FILE, "  union {\n") #end
460					#else
461						object {
462							#if (Write_File) #write (FILE, "  object {\n") #end
463					#end
464
465					#local Cnt=Start_VE_Index;
466
467					#while (Cnt<End_VE)
468						#local Dist = vlength(mechsim:mass(mechsim:viscoelastic(Cnt):index1):position-
469							                    mechsim:mass(mechsim:viscoelastic(Cnt):index2):position);
470						#if (Dist>0.0001)
471							cylinder {
472								mechsim:mass(mechsim:viscoelastic(Cnt):index1):position,
473								mechsim:mass(mechsim:viscoelastic(Cnt):index2):position,
474
475								#if (Write_File)
476									#write (FILE, "    cylinder {<",vstr(3,mechsim:mass(mechsim:viscoelastic(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
477										                              vstr(3,mechsim:mass(mechsim:viscoelastic(Cnt):index2):position,",",0,MSim_File_Decimals), ">, ")
478								#end
479
480								#if (Connect_Rad<0)
481									#local Radius=mechsim:mass(mechsim:viscoelastic(Cnt):index1):radius*0.4;
482								#else
483									#local Radius=Connect_Rad;
484								#end
485
486								Radius
487
488								#if (Write_File)
489									#write (FILE, str(Radius,0,MSim_File_Decimals), " ")
490								#end
491
492								#if (Stress_Fact>0)
493
494									#local Stress=((Dist-mechsim:viscoelastic(Cnt):length)/mechsim:viscoelastic(Cnt):length)*Stress_Fact + 0.5;
495									#local Stress=max(0.0, min(1.0, Stress));
496									texture {
497										pigment { color fn_Stress_CM(Stress, 0, 0) }
498										finish {
499											specular 0.3
500											diffuse 0.7
501										}
502									}
503
504									#if (Write_File)
505										#write (FILE, "texture{pigment{ color rgb <",vstr(3,fn_Stress_CM(Stress,0,0),",",0,4), "> }finish{Fin_Stress}} ")
506									#end
507
508								#end
509							}
510							#if (Write_File)
511								#write (FILE, "}\n")
512							#end
513
514						#end
515
516						#local Cnt=Cnt+1;
517					#end
518
519					#if (Stress_Fact<=0)
520						  texture { MSim_Tex_C }
521
522						#if (Write_File)
523							#write (FILE, "    texture { MSim_Tex_C }\n")
524						#end
525					#end
526						}
527					#if (Write_File)
528						#write (FILE, "  }\n")
529					#end
530				#end
531			#end
532					}
533			#if (Write_File)
534				#write (FILE, "}\n")
535			#end
536		#end
537	#else
538		#if (mechsim:face_count)
539			mesh {
540
541				#if (Write_File)
542					#write (FILE, "mesh {\n")
543				#end
544
545				#local Cnt=Start_Face_Index;
546
547				#while (Cnt<End_Face)
548
549					triangle { mechsim:mass(mechsim:face(Cnt):index1):position,
550						         mechsim:mass(mechsim:face(Cnt):index2):position,
551						         mechsim:mass(mechsim:face(Cnt):index3):position }
552
553					#if (Write_File)
554						#write (FILE, "triangle { <",vstr(3,mechsim:mass(mechsim:face(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
555							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index2):position,",",0,MSim_File_Decimals), ">, <",
556							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index3):position,",",0,MSim_File_Decimals), "> }\n")
557					#end
558
559					#local Cnt=Cnt+1;
560				#end
561
562				texture { MSim_Tex_Mesh }
563			}
564
565			#if (Write_File)
566				#write (FILE, "}\n")
567			#end
568
569		#end
570	#end
571
572	#if (Write_File)
573		#fclose FILE
574	#end
575
576	#debug "Done\n"
577	}
578
579#end
580
581// =======================================================================================
582//  MechSim_Show_Objects()
583//
584//  generates objects representing parts of the simulation topology
585//
586//  Parameters:
587//      Start_Mass_Index       - index of the first mass that should be displayed.
588//                               Should be stored when the topology is generated.
589//      Start_Connection_Index - index of the first connection
590//      Start_Face_Index       - index of the first face
591//      End_Mass_Index         - index of the last mass that should be displayed.
592//                               if <0 all masses until the last are displayed.
593//      End_Connection_Index   - index of the last connection that should be displayed.
594//                               if <0 all connections until the last are displayed.
595//      End_Face_Index         - index of the last face that should be displayed.
596//                               if <0 all faces until the last are displayed.
597//      Connect_Rad            - Radius to use for the connections, values <0 lead
598//                               to using  0.4*mass radius.
599//      Show_Faces             - Only generate a mesh from the faces instead of
600//                               cylinders and spheres.
601//      Stress_Fact            - if >0 the connections are textured to visualize
602//                               the stress.  Values are scaled with this factor.
603//      File_Name              - string, if length is >0 the objects are written to a
604//                               file with that name in addition
605//
606// =======================================================================================
607#macro MechSim_Show_Objects(Start_Mass_Index, Start_Connection_Index, Start_Face_Index,
608                            End_Mass_Index, End_Connection_Index, End_Face_Index,
609                            Connect_Rad, Show_Faces, Stress_Fact, File_Name)
610	MechSim_Show_Objects_X(
611		Start_Mass_Index, Start_Connection_Index, 0, Start_Face_Index,
612		End_Mass_Index, End_Connection_Index, 0, End_Face_Index,
613		Connect_Rad, Show_Faces, Stress_Fact, File_Name
614	)
615
616#end
617
618// =======================================================================================
619//  MechSim_Show_All_Objects()
620//
621//  like MechSim_Show_Objects() but showing all elements of the simulation
622//
623//  Parameters:
624//      Connect_Rad - Radius to use for the connections, values <0 lead to using
625//                    0.4*mass radius
626//      Show_Faces  - Only generate a mesh from the faces instead of
627//                    cylinders and spheres
628//      Stress_Fact - if >0 the connections are textured to visualize the stress.
629//                    values are scaled with this factor
630//      File_Name   - string, if length is >0 the objects are written to a
631//                    file with that name in addition
632//
633// =======================================================================================
634#macro MechSim_Show_All_Objects(Connect_Rad, Show_Faces, Stress_Fact, File_Name)
635
636	MechSim_Show_Objects_X(0,0,0,0, -1, -1, -1, -1, Connect_Rad, Show_Faces, Stress_Fact, File_Name)
637
638#end
639
640// =======================================================================================
641//  MechSim_Show_All_Default()
642//
643//  like MechSim_Show_All_Objects() but using reasonable defaults for parameters
644//
645// =======================================================================================
646#macro MechSim_Show_All_Default()
647
648	#if (mechsim:face_count)
649		MechSim_Show_Objects_X(0,0,0,0, -1, -1, -1, -1, -1, true, -1, "")
650	#else
651		MechSim_Show_Objects_X(0,0,0,0, -1, -1, -1, -1, -1, false, -1, "")
652	#end
653
654#end
655
656// =======================================================================================
657//  MechSim_Show_Patch() macro
658//
659//  generating a mesh corresponding to the topology generated by a
660//  MechSim_Generate_Patch() macro
661//
662//  Parameters:
663//      Start_Face_Index - index of the first face that's part of the patch.  Should
664//                         be stored when the patch is generated
665//      XSize, YSize     - Size of the patch, number of nodes in x- and y-direction
666//      Smooth           - boolean value, if true normal vectors are generated
667//      UV               - boolean value, if true UV-coordinates are generated
668//                         (from 0 to 1 in x-direction)
669//      Stress_Fact      - if >0 the mesh is textured to visualize the stress.
670//                         values are scaled with this factor
671//      File_Name        - string, if length is >0 the mesh is written to a file
672//                         with that name in addition
673//
674// =======================================================================================
675#macro MechSim_Show_Patch(Start_Face_Index, XSize, YSize, Smooth, UV, Stress_Fact, File_Name)
676
677	#if ((mechsim:face_count-Start_Face_Index)>0)
678
679		#if (strlen(File_Name)=0)
680			#local Write_File=false;
681			#debug "Generating Patch Triangle Mesh..."
682		#else
683			#local Write_File=true;
684
685			#fopen FILE File_Name write
686
687			#write (FILE, "// rectangular patch mesh (",str(XSize,0,0),"x",str(YSize,0,0)," vertices)\n")
688			#write (FILE, "// written by MechSim include file version ",str(MSIM_INCLUDE_VERSION,1,1),"\n\n")
689			#write (FILE, "mesh2 {\n\n")
690			#debug concat("Generating Patch Triangle Mesh (writing to file ",File_Name,")...")
691
692		#end
693
694		#local Start_Mass_Index = mechsim:face(Start_Face_Index):index1;
695
696		#if (abs(Stress_Fact)>0)
697
698			#local Vertex_Mult=array[XSize*YSize]
699			#local Vertex_Stress=array[XSize*YSize]
700			#local Vertex_Text=array[XSize*YSize]
701
702			#if (Write_File)
703				#write (FILE, "  #local Vertex_Text=array[",str(XSize*YSize,0,0),"]\n")
704				#write (FILE, "  #local Fin_Stress=\n")
705				#write (FILE, "    finish {\n")
706				#write (FILE, "      specular 0.3\n")
707				#write (FILE, "      diffuse 0.7\n")
708				#write (FILE, "    }\n\n")
709			#end
710
711			#local Cnt=0;
712			#while (Cnt < XSize*YSize)
713				#local Vertex_Mult[Cnt]=0;
714				#local Vertex_Stress[Cnt]=0;
715				#local Cnt=Cnt+1;
716			#end
717
718			#local Cnt=0;
719			#while (Cnt < mechsim:connection_count)
720
721				#if ((mechsim:connection(Cnt):index1 >= Start_Mass_Index) &
722					   (mechsim:connection(Cnt):index2 >= Start_Mass_Index) &
723					   (mechsim:connection(Cnt):index1 < Start_Mass_Index+(XSize*YSize)) &
724					   (mechsim:connection(Cnt):index2 < Start_Mass_Index+(XSize*YSize)))
725
726					#local Dist = vlength(mechsim:mass(mechsim:connection(Cnt):index1):position-
727						                    mechsim:mass(mechsim:connection(Cnt):index2):position);
728
729					#local Stress=((Dist-mechsim:connection(Cnt):length)/mechsim:connection(Cnt):length)*Stress_Fact + 0.5;
730					#local Vertex_Stress[mechsim:connection(Cnt):index1-Start_Mass_Index]=
731					       Vertex_Stress[mechsim:connection(Cnt):index1-Start_Mass_Index]+max(0.0, min(1.0, Stress));
732					#local Vertex_Mult[mechsim:connection(Cnt):index1-Start_Mass_Index]=
733					       Vertex_Mult[mechsim:connection(Cnt):index1-Start_Mass_Index]+1;
734					#local Vertex_Stress[mechsim:connection(Cnt):index2-Start_Mass_Index]=
735					       Vertex_Stress[mechsim:connection(Cnt):index2-Start_Mass_Index]+max(0.0, min(1.0, Stress));
736					#local Vertex_Mult[mechsim:connection(Cnt):index2-Start_Mass_Index]=
737					       Vertex_Mult[mechsim:connection(Cnt):index2-Start_Mass_Index]+1;
738
739				#end
740				#local Cnt=Cnt+1;
741			#end
742
743		#end
744
745		#if (Write_File)
746			#write (FILE, "  vertex_vectors {\n")
747			#write (FILE, "    ",str(XSize*YSize,0,0))
748		#end
749
750		mesh2 {
751			vertex_vectors {
752				(XSize*YSize)
753
754				#local Cnt=Start_Mass_Index;
755				#while (Cnt < XSize*YSize + Start_Mass_Index)
756					,
757					mechsim:mass(Cnt):position
758
759					#if (Write_File)
760						#write (FILE, ",\n    <",vstr(3,mechsim:mass(Cnt):position,",",0,MSim_File_Decimals), ">")
761					#end
762
763					#local Cnt=Cnt+1;
764				#end
765			}
766
767			#if (Write_File)
768				#write (FILE, "\n  }\n")
769			#end
770
771			#if (Smooth)
772
773				#if (Write_File)
774					#write (FILE, "  normal_vectors {\n")
775					#write (FILE, "    ",str(XSize*YSize,0,0))
776				#end
777
778				normal_vectors {
779					(XSize*YSize)
780
781					#local Cnt=Start_Mass_Index;
782					#while (Cnt < XSize*YSize + Start_Mass_Index)
783						,
784
785						#local Pos=<mod(Cnt-Start_Mass_Index, XSize), div(Cnt-Start_Mass_Index, XSize)>;
786
787						#if (Pos.x=0)
788							#if (Pos.y=0)
789								#local Norm=vcross(mechsim:mass(Cnt+1):position-mechsim:mass(Cnt):position,
790									                 mechsim:mass(Cnt+XSize):position-mechsim:mass(Cnt):position);
791							#else
792								#if (Pos.y=YSize-1)
793									#local Norm=vcross(mechsim:mass(Cnt+1):position-mechsim:mass(Cnt):position,
794										                 mechsim:mass(Cnt):position-mechsim:mass(Cnt-XSize):position);
795								#else /* Pos.y middle */
796									#local Norm=vcross(mechsim:mass(Cnt+1):position-mechsim:mass(Cnt):position,
797										                 mechsim:mass(Cnt+XSize):position-mechsim:mass(Cnt-XSize):position);
798								#end
799							#end
800						#else
801							#if (Pos.x=XSize-1)
802								#if (Pos.y=0)
803									#local Norm=vcross(mechsim:mass(Cnt):position-mechsim:mass(Cnt-1):position,
804										                 mechsim:mass(Cnt+XSize):position-mechsim:mass(Cnt):position);
805								#else
806									#if (Pos.y=YSize-1)
807										#local Norm=vcross(mechsim:mass(Cnt):position-mechsim:mass(Cnt-1):position,
808											                 mechsim:mass(Cnt):position-mechsim:mass(Cnt-XSize):position);
809
810									#else /* Pos.y middle */
811										#local Norm=vcross(mechsim:mass(Cnt):position-mechsim:mass(Cnt-1):position,
812											                 mechsim:mass(Cnt+XSize):position-mechsim:mass(Cnt-XSize):position);
813									#end
814								#end
815							#else /* Pos.x middle */
816								#if (Pos.y=0)
817									#local Norm=vcross(mechsim:mass(Cnt+1):position-mechsim:mass(Cnt-1):position,
818										                 mechsim:mass(Cnt+XSize):position-mechsim:mass(Cnt):position);
819								#else
820									#if (Pos.y=YSize-1)
821										#local Norm=vcross(mechsim:mass(Cnt+1):position-mechsim:mass(Cnt-1):position,
822											                 mechsim:mass(Cnt):position-mechsim:mass(Cnt-XSize):position);
823									#else /* Pos.y and Pos.x middle */
824										#local Norm=vcross(mechsim:mass(Cnt+1):position-mechsim:mass(Cnt-1):position,
825											                 mechsim:mass(Cnt+XSize):position-mechsim:mass(Cnt-XSize):position);
826									#end
827								#end
828							#end
829						#end
830
831						Norm
832
833						#if (Write_File)
834							#write (FILE, ",\n    <",vstr(3,Norm,",",0,MSim_File_Decimals), ">")
835						#end
836
837						#local Cnt=Cnt+1;
838					#end
839				}
840
841				#if (Write_File)
842					#write (FILE, "\n  }\n")
843				#end
844
845			#end
846
847			#if (UV)
848
849				#if (Write_File)
850					#write (FILE, "  uv_vectors {\n")
851					#write (FILE, "    ",str(XSize*YSize,0,0))
852				#end
853
854				uv_vectors {
855					(XSize*YSize)
856
857					#local Cnt=Start_Mass_Index;
858					#while (Cnt < XSize*YSize + Start_Mass_Index)
859						,
860						#local UV_Pos=<mod(Cnt-Start_Mass_Index, XSize), div(Cnt-Start_Mass_Index, XSize)>/(XSize-1);
861
862						UV_Pos
863
864						#if (Write_File)
865							#write (FILE, ",\n    <",vstr(2,UV_Pos,",",0,MSim_File_Decimals), ">")
866						#end
867
868						#local Cnt=Cnt+1;
869					#end
870
871				}
872
873				#if (Write_File)
874					#write (FILE, "\n  }\n")
875				#end
876
877			#end
878
879			#if (abs(Stress_Fact)>0)
880
881				#if (Write_File)
882					#write (FILE, "  texture_list {\n")
883					#write (FILE, "    ",str(XSize*YSize,0,0))
884				#end
885
886				texture_list {
887					(XSize*YSize)
888
889					#local Cnt=0;
890					#while (Cnt < XSize*YSize)
891
892						#local Vertex_Text[Cnt]=
893						texture {
894							pigment { color fn_Stress_CM(Vertex_Stress[Cnt]/Vertex_Mult[Cnt], 0, 0) }
895							finish {
896								specular 0.3
897								diffuse 0.7
898							}
899						}
900
901						,
902
903						texture { Vertex_Text[Cnt] }
904
905						#if (Write_File)
906							#write (FILE, "\n    #local Vertex_Text[",str(Cnt,0,0),"]=texture{pigment{ color rgb <",
907								            vstr(3, fn_Stress_CM(Vertex_Stress[Cnt]/Vertex_Mult[Cnt],0,0),",",0,4),
908								            "> }finish{Fin_Stress}}\n")
909
910							#write (FILE, "    , texture { Vertex_Text[",str(Cnt,0,0),"] }")
911						#end
912
913						#local Cnt=Cnt+1;
914					#end
915				}
916
917				#if (Write_File)
918					#write (FILE, "\n  }\n")
919				#end
920
921			#end
922
923			#if (Write_File)
924				#write (FILE, "  face_indices {\n")
925				#write (FILE, "    ",str((XSize-1)*(YSize-1)*2,0,0))
926			#end
927
928			face_indices {
929				(XSize-1)*(YSize-1)*2
930
931				#local Cnt=Start_Face_Index;
932
933				#while (Cnt< (XSize-1)*(YSize-1)*2 + Start_Face_Index)
934					,
935					<mechsim:face(Cnt):index1-Start_Mass_Index,
936					 mechsim:face(Cnt):index2-Start_Mass_Index,
937					 mechsim:face(Cnt):index3-Start_Mass_Index>
938
939					#if (Write_File)
940						#write (FILE, ",\n    <",vstr(3,<mechsim:face(Cnt):index1-Start_Mass_Index,
941							                               mechsim:face(Cnt):index2-Start_Mass_Index,
942							                               mechsim:face(Cnt):index3-Start_Mass_Index>,",",0,0), ">")
943					#end
944
945					#if (Stress_Fact>0)
946						,
947						mechsim:face(Cnt):index1-Start_Mass_Index,
948						mechsim:face(Cnt):index2-Start_Mass_Index,
949						mechsim:face(Cnt):index3-Start_Mass_Index
950
951						#if (Write_File)
952							#write (FILE, ", ",vstr(3,<mechsim:face(Cnt):index1-Start_Mass_Index,
953								                         mechsim:face(Cnt):index2-Start_Mass_Index,
954								                         mechsim:face(Cnt):index3-Start_Mass_Index>,",",0,0))
955						#end
956
957					#end
958
959					#local Cnt=Cnt+1;
960				#end
961			}
962
963			//texture { MSim_Tex_Mesh }
964		}
965
966		#if (Write_File)
967			#write (FILE, "\n  }\n}\n")
968			#fclose FILE
969		#end
970
971	#end
972
973	#debug "Done\n"
974
975#end
976
977// =======================================================================================
978//  MechSim_Show_Grid() macro
979//
980//  generating a mesh for the outer surface of a grid generated with the
981//  MechSim_Generate_Grid() macro (with 'Faces' parameter true)
982//
983//  Parameters:
984//      Start_Face_Index - index of the first face that's part of the patch.  Should
985//                         be stored when the patch is generated
986//      XSize, YSize     - Size of the patch, number of nodes in x- and y-direction
987//      Smooth           - boolean value, if true normal vectors are generated
988//      UV               - boolean value, if true UV-coordinates are generated
989//                         (from 0 to 1 in x-direction)
990//      Stress_Fact      - if >0 the mesh is textured to visualize the stress.
991//                         values are scaled with this factor
992//      File_Name        - string, if length is >0 the mesh is written to a file
993//                         with that name in addition
994//
995// =======================================================================================
996#macro MechSim_Show_Grid(Start_Face_Index, XSize, YSize, ZSize, Smooth, UV, Stress_Fact, File_Name)
997
998	#local FCount=(XSize-1)*(YSize-1)*4 + (XSize-1)*(ZSize-1)*4 + (ZSize-1)*(YSize-1)*4;
999
1000	#if ((mechsim:face_count-Start_Face_Index)>=FCount)
1001
1002		#if (strlen(File_Name)=0)
1003			#local Write_File=false;
1004			#debug "Generating Grid Surface Triangle Mesh...\n"
1005		#else
1006			#local Write_File=true;
1007
1008			#fopen FILE File_Name write
1009
1010			#write (FILE, "// grid mesh (",str(XSize,0,0),"x",str(YSize,0,0),"x",str(ZSize,0,0)," vertices)\n")
1011			#write (FILE, "// written by MechSim include file version ",str(MSIM_INCLUDE_VERSION,1,1),"\n\n")
1012			#debug concat("Generating Grid Triangle Mesh (writing to file ",File_Name,")...\n")
1013
1014		#end
1015
1016		#local Start_Mass_Index = mechsim:face(Start_Face_Index):index1;
1017		#local Count=(XSize*YSize*ZSize);
1018		#local EPS=1e-6;
1019
1020		#if (abs(Stress_Fact)>0)
1021
1022			#local Vertex_Mult=array[XSize*YSize*ZSize]
1023			#local Vertex_Stress=array[XSize*YSize*ZSize]
1024			#local Vertex_Text=array[XSize*YSize*ZSize]
1025
1026			#if (Write_File)
1027				#write (FILE, "  #local Vertex_Text=array[",str(XSize*YSize*ZSize,0,0),"]\n")
1028				#write (FILE, "  #local Fin_Stress=\n")
1029				#write (FILE, "    finish {\n")
1030				#write (FILE, "      specular 0.3\n")
1031				#write (FILE, "      diffuse 0.7\n")
1032				#write (FILE, "    }\n\n")
1033			#end
1034
1035			#local Cnt=0;
1036			#while (Cnt < Count)
1037				#local Vertex_Mult[Cnt]=0;
1038				#local Vertex_Stress[Cnt]=0;
1039				#local Cnt=Cnt+1;
1040			#end
1041
1042			#local Cnt=0;
1043			#while (Cnt < mechsim:viscoelastic_count)
1044
1045				#if ((mechsim:viscoelastic(Cnt):index1 >= Start_Mass_Index) &
1046					   (mechsim:viscoelastic(Cnt):index2 >= Start_Mass_Index) &
1047					   (mechsim:viscoelastic(Cnt):index1 < Start_Mass_Index+Count) &
1048					   (mechsim:viscoelastic(Cnt):index2 < Start_Mass_Index+Count))
1049
1050					#local Dist = vlength(mechsim:mass(mechsim:viscoelastic(Cnt):index1):position-
1051						                    mechsim:mass(mechsim:viscoelastic(Cnt):index2):position);
1052
1053					#local Stress=((Dist-mechsim:viscoelastic(Cnt):length)/mechsim:viscoelastic(Cnt):length)*Stress_Fact + 0.5;
1054					#local Vertex_Stress[mechsim:viscoelastic(Cnt):index1-Start_Mass_Index]=
1055					       Vertex_Stress[mechsim:viscoelastic(Cnt):index1-Start_Mass_Index]+max(0.0, min(1.0, Stress));
1056					#local Vertex_Mult[mechsim:viscoelastic(Cnt):index1-Start_Mass_Index]=
1057					       Vertex_Mult[mechsim:viscoelastic(Cnt):index1-Start_Mass_Index]+1;
1058					#local Vertex_Stress[mechsim:viscoelastic(Cnt):index2-Start_Mass_Index]=
1059					       Vertex_Stress[mechsim:viscoelastic(Cnt):index2-Start_Mass_Index]+max(0.0, min(1.0, Stress));
1060					#local Vertex_Mult[mechsim:viscoelastic(Cnt):index2-Start_Mass_Index]=
1061					       Vertex_Mult[mechsim:viscoelastic(Cnt):index2-Start_Mass_Index]+1;
1062
1063				#end
1064				#local Cnt=Cnt+1;
1065			#end
1066
1067			#local Cnt=0;
1068			#while (Cnt < mechsim:connection_count)
1069
1070				#if ((mechsim:connection(Cnt):index1 >= Start_Mass_Index) &
1071					   (mechsim:connection(Cnt):index2 >= Start_Mass_Index) &
1072					   (mechsim:connection(Cnt):index1 < Start_Mass_Index+Count) &
1073					   (mechsim:connection(Cnt):index2 < Start_Mass_Index+Count))
1074
1075					#local Dist = vlength(mechsim:mass(mechsim:connection(Cnt):index1):position-
1076						                    mechsim:mass(mechsim:connection(Cnt):index2):position);
1077
1078					#local Stress=((Dist-mechsim:connection(Cnt):length)/mechsim:connection(Cnt):length)*Stress_Fact + 0.5;
1079					#local Vertex_Stress[mechsim:connection(Cnt):index1-Start_Mass_Index]=
1080					       Vertex_Stress[mechsim:connection(Cnt):index1-Start_Mass_Index]+max(0.0, min(1.0, Stress));
1081					#local Vertex_Mult[mechsim:connection(Cnt):index1-Start_Mass_Index]=
1082					       Vertex_Mult[mechsim:connection(Cnt):index1-Start_Mass_Index]+1;
1083					#local Vertex_Stress[mechsim:connection(Cnt):index2-Start_Mass_Index]=
1084					       Vertex_Stress[mechsim:connection(Cnt):index2-Start_Mass_Index]+max(0.0, min(1.0, Stress));
1085					#local Vertex_Mult[mechsim:connection(Cnt):index2-Start_Mass_Index]=
1086					       Vertex_Mult[mechsim:connection(Cnt):index2-Start_Mass_Index]+1;
1087
1088				#end
1089				#local Cnt=Cnt+1;
1090			#end
1091
1092			#local Cnt=0;
1093			#while (Cnt < Count)
1094
1095				#local Vertex_Text[Cnt]=
1096				texture {
1097					pigment { color fn_Stress_CM(Vertex_Stress[Cnt]/Vertex_Mult[Cnt], 0, 0) }
1098					finish {
1099						specular 0.3
1100						diffuse 0.7
1101					}
1102				}
1103
1104				#if (Write_File)
1105					#write (FILE, "  #local Vertex_Text[",str(Cnt,0,0),"]=texture{pigment{ color rgb <",
1106						      vstr(3, fn_Stress_CM(Vertex_Stress[Cnt]/Vertex_Mult[Cnt],0,0),",",0,4),
1107						      "> }finish{Fin_Stress}}\n")
1108				#end
1109
1110				#local Cnt=Cnt+1;
1111			#end
1112
1113		#end
1114
1115		mesh {
1116
1117			#if (Write_File)
1118				#write (FILE, "\nmesh {\n")
1119			#end
1120
1121			#if (Smooth)
1122
1123				#local Normals=array[Count][3]
1124
1125				#local Cnt=0;
1126				#while (Cnt<Count)
1127					#local Normals[Cnt][0]=<0,0,0>;
1128					#local Normals[Cnt][1]=<0,0,0>;
1129					#local Normals[Cnt][2]=<0,0,0>;
1130					#local Cnt=Cnt+1;
1131				#end
1132
1133				#local Cnt=Start_Face_Index;
1134
1135				#while (Cnt<Start_Face_Index+FCount)
1136
1137					#local Norm=vnormalize(vcross(mechsim:mass(mechsim:face(Cnt):index1):position-mechsim:mass(mechsim:face(Cnt):index2):position,
1138						                            mechsim:mass(mechsim:face(Cnt):index1):position-mechsim:mass(mechsim:face(Cnt):index3):position));
1139
1140					#local Coord1=<mod(mechsim:face(Cnt):index1-Start_Mass_Index, XSize),
1141					               div(mod(mechsim:face(Cnt):index1-Start_Mass_Index, XSize*YSize), XSize),
1142					               div(mechsim:face(Cnt):index1-Start_Mass_Index, XSize*YSize)>;
1143
1144					#local Coord2=<mod(mechsim:face(Cnt):index2-Start_Mass_Index, XSize),
1145					               div(mod(mechsim:face(Cnt):index2-Start_Mass_Index, XSize*YSize), XSize),
1146					               div(mechsim:face(Cnt):index2-Start_Mass_Index, XSize*YSize)>;
1147
1148					#local Coord3=<mod(mechsim:face(Cnt):index3-Start_Mass_Index, XSize),
1149					               div(mod(mechsim:face(Cnt):index3-Start_Mass_Index, XSize*YSize), XSize),
1150					               div(mechsim:face(Cnt):index3-Start_Mass_Index, XSize*YSize)>;
1151
1152					#if ((abs(Coord1.x-Coord2.x)<EPS)&(abs(Coord2.x-Coord3.x)<EPS))
1153						// ------ x-negative/positive Face ------
1154						#local Normals[mechsim:face(Cnt):index1-Start_Mass_Index][0]=
1155						       Normals[mechsim:face(Cnt):index1-Start_Mass_Index][0] + Norm;
1156						#local Normals[mechsim:face(Cnt):index2-Start_Mass_Index][0]=
1157						       Normals[mechsim:face(Cnt):index2-Start_Mass_Index][0] + Norm;
1158						#local Normals[mechsim:face(Cnt):index3-Start_Mass_Index][0]=
1159						       Normals[mechsim:face(Cnt):index3-Start_Mass_Index][0] + Norm;
1160					#end
1161
1162					#if ((abs(Coord1.y-Coord2.y)<EPS)&(abs(Coord2.y-Coord3.y)<EPS))
1163						// ------ y-negative/positive Face ------
1164						#local Normals[mechsim:face(Cnt):index1-Start_Mass_Index][1]=
1165						       Normals[mechsim:face(Cnt):index1-Start_Mass_Index][1] + Norm;
1166						#local Normals[mechsim:face(Cnt):index2-Start_Mass_Index][1]=
1167						       Normals[mechsim:face(Cnt):index2-Start_Mass_Index][1] + Norm;
1168						#local Normals[mechsim:face(Cnt):index3-Start_Mass_Index][1]=
1169						       Normals[mechsim:face(Cnt):index3-Start_Mass_Index][1] + Norm;
1170					#end
1171
1172					#if ((abs(Coord1.z-Coord2.z)<EPS)&(abs(Coord2.z-Coord3.z)<EPS))
1173						// ------ z-negative/positive Face ------
1174						#local Normals[mechsim:face(Cnt):index1-Start_Mass_Index][2]=
1175						       Normals[mechsim:face(Cnt):index1-Start_Mass_Index][2] + Norm;
1176						#local Normals[mechsim:face(Cnt):index2-Start_Mass_Index][2]=
1177						       Normals[mechsim:face(Cnt):index2-Start_Mass_Index][2] + Norm;
1178						#local Normals[mechsim:face(Cnt):index3-Start_Mass_Index][2]=
1179						       Normals[mechsim:face(Cnt):index3-Start_Mass_Index][2] + Norm;
1180					#end
1181
1182					#local Cnt=Cnt+1;
1183				#end
1184
1185				#local Cnt=Start_Face_Index;
1186
1187				#while (Cnt<Start_Face_Index+FCount)
1188
1189					#if ( // --- is x-Face? ---
1190						   (vlength(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][0])>0.5)&
1191						   (vlength(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][0])>0.5)&
1192						   (vlength(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][0])>0.5)
1193					    )
1194						smooth_triangle {
1195							mechsim:mass(mechsim:face(Cnt):index1):position,
1196							vnormalize(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][0]),
1197							mechsim:mass(mechsim:face(Cnt):index2):position,
1198							vnormalize(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][0]),
1199							mechsim:mass(mechsim:face(Cnt):index3):position,
1200							vnormalize(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][0])
1201							#if (abs(Stress_Fact)>0)
1202								texture_list {
1203									Vertex_Text[mechsim:face(Cnt):index1]
1204									Vertex_Text[mechsim:face(Cnt):index2]
1205									Vertex_Text[mechsim:face(Cnt):index3]
1206								}
1207							#end
1208						}
1209
1210						#if (Write_File)
1211							#write (FILE, "smooth_triangle { <",vstr(3,mechsim:mass(mechsim:face(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
1212								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][0]),",",0,MSim_File_Decimals), ">, <",
1213								                                  vstr(3,mechsim:mass(mechsim:face(Cnt):index2):position,",",0,MSim_File_Decimals), ">, <",
1214								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][0]),",",0,MSim_File_Decimals), ">, <",
1215								                                  vstr(3,mechsim:mass(mechsim:face(Cnt):index3):position,",",0,MSim_File_Decimals), ">, <",
1216								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][0]),",",0,MSim_File_Decimals), ">")
1217
1218							#if (abs(Stress_Fact)>0)
1219								#write (FILE, "\n  texture_list { Vertex_Text[",
1220									      str(mechsim:face(Cnt):index1,0,0), "] Vertex_Text[",
1221									      str(mechsim:face(Cnt):index2,0,0), "] Vertex_Text[",
1222									      str(mechsim:face(Cnt):index3,0,0), "] } }\n"
1223							#else
1224								#write (FILE, " }\n")
1225							#end
1226						#end
1227
1228					#end
1229
1230					#if ( // --- is y-Face? ---
1231						   (vlength(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][1])>0.5)&
1232						   (vlength(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][1])>0.5)&
1233						   (vlength(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][1])>0.5)
1234					    )
1235						smooth_triangle {
1236							mechsim:mass(mechsim:face(Cnt):index1):position,
1237							vnormalize(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][1]),
1238							mechsim:mass(mechsim:face(Cnt):index2):position,
1239							vnormalize(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][1]),
1240							mechsim:mass(mechsim:face(Cnt):index3):position,
1241							vnormalize(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][1])
1242							#if (abs(Stress_Fact)>0)
1243								texture_list {
1244									Vertex_Text[mechsim:face(Cnt):index1]
1245									Vertex_Text[mechsim:face(Cnt):index2]
1246									Vertex_Text[mechsim:face(Cnt):index3]
1247								}
1248							#end
1249						}
1250
1251						#if (Write_File)
1252							#write (FILE, "smooth_triangle { <",vstr(3,mechsim:mass(mechsim:face(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
1253								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][1]),",",0,MSim_File_Decimals), ">, <",
1254								                                  vstr(3,mechsim:mass(mechsim:face(Cnt):index2):position,",",0,MSim_File_Decimals), ">, <",
1255								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][1]),",",0,MSim_File_Decimals), ">, <",
1256								                                  vstr(3,mechsim:mass(mechsim:face(Cnt):index3):position,",",0,MSim_File_Decimals), ">, <",
1257								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][1]),",",0,MSim_File_Decimals), ">")
1258							#if (abs(Stress_Fact)>0)
1259								#write (FILE, "\n  texture_list { Vertex_Text[",
1260									      str(mechsim:face(Cnt):index1,0,0), "] Vertex_Text[",
1261									      str(mechsim:face(Cnt):index2,0,0), "] Vertex_Text[",
1262									      str(mechsim:face(Cnt):index3,0,0), "] } }\n"
1263							#else
1264								#write (FILE, " }\n")
1265							#end
1266						#end
1267
1268					#end
1269
1270					#if ( // --- is z-Face? ---
1271						   (vlength(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][2])>0.5)&
1272						   (vlength(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][2])>0.5)&
1273						   (vlength(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][2])>0.5)
1274					    )
1275						smooth_triangle {
1276							mechsim:mass(mechsim:face(Cnt):index1):position,
1277							vnormalize(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][2]),
1278							mechsim:mass(mechsim:face(Cnt):index2):position,
1279							vnormalize(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][2]),
1280							mechsim:mass(mechsim:face(Cnt):index3):position,
1281							vnormalize(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][2])
1282							#if (abs(Stress_Fact)>0)
1283								texture_list {
1284									Vertex_Text[mechsim:face(Cnt):index1]
1285									Vertex_Text[mechsim:face(Cnt):index2]
1286									Vertex_Text[mechsim:face(Cnt):index3]
1287								}
1288							#end
1289						}
1290
1291						#if (Write_File)
1292							#write (FILE, "smooth_triangle { <",vstr(3,mechsim:mass(mechsim:face(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
1293								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index1-Start_Mass_Index][2]),",",0,MSim_File_Decimals), ">, <",
1294								                                  vstr(3,mechsim:mass(mechsim:face(Cnt):index2):position,",",0,MSim_File_Decimals), ">, <",
1295								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index2-Start_Mass_Index][2]),",",0,MSim_File_Decimals), ">, <",
1296								                                  vstr(3,mechsim:mass(mechsim:face(Cnt):index3):position,",",0,MSim_File_Decimals), ">, <",
1297								                                  vstr(3,vnormalize(Normals[mechsim:face(Cnt):index3-Start_Mass_Index][2]),",",0,MSim_File_Decimals), ">")
1298							#if (abs(Stress_Fact)>0)
1299								#write (FILE, "\n  texture_list { Vertex_Text[",
1300									      str(mechsim:face(Cnt):index1,0,0), "] Vertex_Text[",
1301									      str(mechsim:face(Cnt):index2,0,0), "] Vertex_Text[",
1302									      str(mechsim:face(Cnt):index3,0,0), "] } }\n"
1303							#else
1304								#write (FILE, " }\n")
1305							#end
1306						#end
1307
1308					#end
1309					#local Cnt=Cnt+1;
1310
1311				#end
1312
1313			#else // not Smooth
1314
1315				#local Cnt=Start_Face_Index;
1316
1317				#while (Cnt<Start_Face_Index+FCount)
1318
1319					triangle {
1320						mechsim:mass(mechsim:face(Cnt):index1):position,
1321						mechsim:mass(mechsim:face(Cnt):index2):position,
1322						mechsim:mass(mechsim:face(Cnt):index3):position
1323						#if (abs(Stress_Fact)>0)
1324							texture_list {
1325								Vertex_Text[mechsim:face(Cnt):index1]
1326								Vertex_Text[mechsim:face(Cnt):index2]
1327								Vertex_Text[mechsim:face(Cnt):index3]
1328							}
1329						#end
1330					}
1331
1332					#if (Write_File)
1333						#write (FILE, "triangle { <",vstr(3,mechsim:mass(mechsim:face(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
1334							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index2):position,",",0,MSim_File_Decimals), ">, <",
1335							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index3):position,",",0,MSim_File_Decimals), ">")
1336						#if (abs(Stress_Fact)>0)
1337							#write (FILE, "\n  texture_list { Vertex_Text[",
1338								      str(mechsim:face(Cnt):index1,0,0), "] Vertex_Text[",
1339									    str(mechsim:face(Cnt):index2,0,0), "] Vertex_Text[",
1340									    str(mechsim:face(Cnt):index3,0,0), "] } }\n"
1341						#else
1342							#write (FILE, " }\n")
1343						#end
1344					#end
1345
1346					#local Cnt=Cnt+1;
1347				#end
1348
1349			#end
1350
1351			texture { MSim_Tex_Mesh }
1352		}
1353
1354		#if (Write_File)
1355			#write (FILE, "}\n")
1356		#end
1357
1358	#end
1359
1360	#debug "Done\n"
1361
1362#end
1363
1364// =======================================================================================
1365//  MechSim_Show_Sphere() macro
1366//
1367//  generating a mesh for the outer surface of a grid generated with the
1368//  MechSim_Generate_Sphere() macro (fith 'Faces' parameter true)
1369//
1370//  Parameters:
1371//      Start_Face_Index - index of the first face that's part of the patch.  Should
1372//                         be stored when the patch is generated
1373//      XSize, YSize     - Size of the patch, number of nodes in x- and y-direction
1374//      Smooth           - boolean value, if true normal vectors are generated
1375//      UV               - boolean value, if true UV-coordinates are generated
1376//                         (from 0 to 1 in x-direction)
1377//      Stress_Fact      - if >0 the mesh is textured to visualize the stress.
1378//                         values are scaled with this factor
1379//      File_Name        - string, if length is >0 the mesh is written to a file
1380//                         with that name in addition
1381//
1382// =======================================================================================
1383#macro MechSim_Show_Sphere(Start_Face_Index, Face_Count, Smooth, UV, Stress_Fact, File_Name)
1384
1385	#if ((mechsim:face_count-Start_Face_Index)>=Face_Count)
1386
1387		#if (strlen(File_Name)=0)
1388			#local Write_File=false;
1389			#debug "Generating Sphere Surface Triangle Mesh...\n"
1390		#else
1391			#local Write_File=true;
1392
1393			#fopen FILE File_Name write
1394
1395			#write (FILE, "// sphere mesh (",str(XSize,0,0),"x",str(YSize,0,0),"x",str(ZSize,0,0)," vertices)\n")
1396			#write (FILE, "// written by MechSim include file version ",str(MSIM_INCLUDE_VERSION,1,1),"\n\n")
1397			#write (FILE, "mesh {\n\n")
1398			#debug concat("Generating Sphere Triangle Mesh (writing to file ",File_Name,")...\n")
1399
1400		#end
1401
1402		mesh {
1403
1404			#if (Write_File)
1405				#write (FILE, "mesh {\n")
1406			#end
1407
1408			#if (Smooth)
1409
1410				#local Center_Pos=mechsim:mass(mechsim:face(Start_Face_Index):index1-1):position;
1411
1412				#local Cnt=Start_Face_Index;
1413
1414				#while (Cnt<Start_Face_Index+Face_Count)
1415
1416					smooth_triangle { mechsim:mass(mechsim:face(Cnt):index1):position,
1417						                vnormalize(mechsim:mass(mechsim:face(Cnt):index1):position-Center_Pos),
1418						                mechsim:mass(mechsim:face(Cnt):index2):position,
1419						                vnormalize(mechsim:mass(mechsim:face(Cnt):index2):position-Center_Pos),
1420						                mechsim:mass(mechsim:face(Cnt):index3):position,
1421						                vnormalize(mechsim:mass(mechsim:face(Cnt):index3):position-Center_Pos) }
1422
1423					#if (Write_File)
1424						#write (FILE, "triangle { <",vstr(3,mechsim:mass(mechsim:face(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
1425							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index2):position,",",0,MSim_File_Decimals), ">, <",
1426							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index3):position,",",0,MSim_File_Decimals), "> }\n")
1427					#end
1428
1429					#local Cnt=Cnt+1;
1430				#end
1431
1432			#else // not Smooth
1433
1434				#local Cnt=Start_Face_Index;
1435
1436				#while (Cnt<Start_Face_Index+Face_Count)
1437
1438					triangle { mechsim:mass(mechsim:face(Cnt):index1):position,
1439						         mechsim:mass(mechsim:face(Cnt):index2):position,
1440						         mechsim:mass(mechsim:face(Cnt):index3):position }
1441
1442					#if (Write_File)
1443						#write (FILE, "triangle { <",vstr(3,mechsim:mass(mechsim:face(Cnt):index1):position,",",0,MSim_File_Decimals), ">, <",
1444							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index2):position,",",0,MSim_File_Decimals), ">, <",
1445							                           vstr(3,mechsim:mass(mechsim:face(Cnt):index3):position,",",0,MSim_File_Decimals), "> }\n")
1446					#end
1447
1448					#local Cnt=Cnt+1;
1449				#end
1450
1451			#end
1452
1453			texture { MSim_Tex_Mesh }
1454		}
1455
1456		#if (Write_File)
1457			#write (FILE, "}\n")
1458		#end
1459
1460	#end
1461
1462	#debug "Done\n"
1463
1464#end
1465
1466// =======================================================================================
1467//  MechSim_Show_Con() macro
1468//
1469//  generating a cylinder representing a connection
1470//
1471//  Parameters:
1472//      Idx - connection index
1473//
1474// =======================================================================================
1475
1476#macro MechSim_Show_Con(Idx)
1477
1478  #local Dist = vlength(mechsim:mass(mechsim:connection(Idx):index1):position-
1479		                    mechsim:mass(mechsim:connection(Idx):index2):position);
1480  #if (Dist>0.0001)
1481		cylinder {
1482			mechsim:mass(mechsim:connection(Idx):index1):position,
1483			mechsim:mass(mechsim:connection(Idx):index2):position,
1484			(mechsim:mass(mechsim:connection(Idx):index1):radius+mechsim:mass(mechsim:connection(Idx):index2):radius)*0.25
1485		}
1486	#end
1487#end
1488
1489// =======================================================================================
1490//  MechSim_Show_Con_VE() macro
1491//
1492//  generating a cylinder representing a viscoelastic connection
1493//
1494//  Parameters:
1495//      Idx - connection index
1496//
1497// =======================================================================================
1498
1499#macro MechSim_Show_Con_VE(Idx)
1500
1501  #local Dist = vlength(mechsim:mass(mechsim:viscoelastic(Idx):index1):position-
1502		                    mechsim:mass(mechsim:viscoelastic(Idx):index2):position);
1503  #if (Dist>0.0001)
1504		cylinder {
1505			mechsim:mass(mechsim:viscoelastic(Idx):index1):position,
1506			mechsim:mass(mechsim:viscoelastic(Idx):index2):position,
1507			(mechsim:mass(mechsim:viscoelastic(Idx):index1):radius+mechsim:mass(mechsim:viscoelastic(Idx):index2):radius)*0.25
1508		}
1509	#end
1510#end
1511
1512
1513// #######################################################################################
1514//   Grid topology generation macros
1515// #######################################################################################
1516
1517// =======================================================================================
1518//  MechSim_Generate_Grid_X() macro
1519//
1520//  basis macro for generating 3D grid topologies.
1521//  Do not use this but the wrapper macros below.
1522//
1523//  Parameters:
1524//      Velocity     - vector defining the common starting velocity of all masses.
1525//      Radius       - radius of all masses.
1526//      fn_Density   - user defined function controlling the density of the masses.
1527//                     x, y and z are evaluated in [0..1] range.
1528//      fn_Stiffness - user defined function controlling the stiffness of the connections.
1529//      fn_Damping   - user defined function controlling the damping of the connections.
1530//      VE_Elements  - array with the parameters for viscoelastic connections
1531//      VE_Accuracy  - accuracy value for viscoelastic connections -
1532//                     <= 0 means to create normal connections
1533//      Faces        - Boolean value controlling whether faces are generated for the surface.
1534//                     If true faces are generated on the outside shape.
1535//      Cube_Scale   - 3D vector controlling the distances in the grid. It defines the size of an elementary cell.
1536//      Grid_Size    - 3D vector containing the number of masses in all three directions.
1537//      Transf       - Transform applied to the mass positions
1538//      fn_Fixed     - user defined function controlling which masses are fixed.
1539//									   x, y and z are evaluated in [0..1] range. For function values > 0 the masses are fixed.
1540//      fn_Attach    - user defined function controlling which masses are attached.
1541//                     x, y and z are evaluated in [0..1] range. The function value determines the attachment index.
1542//      fn_Force     - user defined function controlling custom forces.
1543//                     x, y and z are evaluated in [0..1] range. The function value determines the custom force index.
1544//      Connect_Arr  - Array containing weights for connection stiffness and damping.
1545//
1546// =======================================================================================
1547#macro MechSim_Generate_Grid_X(Velocity, Radius, fn_Density, fn_Stiffness, fn_Damping, VE_Elements, VE_Accuracy, Faces, Cube_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr)
1548
1549	#debug "Generating Grid..."
1550
1551	#local Vel=Velocity+<0,0,0>;
1552	#local CubeScale=Cube_Scale+<0,0,0>;
1553	#local GridSize=Grid_Size+<0,0,0>;
1554
1555	#local EPS=0.001*CubeScale.x;
1556
1557	#local StIdx=mechsim:mass_count;
1558	#local Count=(GridSize.x*GridSize.y*GridSize.z);
1559	#local Diagonal=dimension_size(Connect_Arr, 1);
1560	#if (Connect_Arr[0]=0)
1561		#local Diagonal=0;
1562	#end
1563
1564	#local Cnt=0;
1565
1566	#while (Cnt<Count)
1567
1568		#local Coord=<mod(Cnt, GridSize.x),
1569		              div(mod(Cnt, GridSize.x*GridSize.y), GridSize.x),
1570		              div(Cnt, GridSize.x*GridSize.y)>;
1571
1572
1573		#local Coord2=<Coord.x*CubeScale.x,
1574		               Coord.y*CubeScale.y,
1575		               Coord.z*CubeScale.z>;
1576
1577		#local CoordF=<Coord.x/(GridSize.x-1),
1578                   Coord.y/(GridSize.y-1),
1579                   Coord.z/(GridSize.z-1)>;
1580
1581		mass {
1582			vtransform(Coord2, Transf), Vel, Radius density fn_Density(CoordF.x, CoordF.y, CoordF.z)
1583			#if ( fn_Fixed(CoordF.x, CoordF.y, CoordF.z)>0 )
1584				fixed on
1585			#else
1586				#local Attach=fn_Attach(CoordF.x, CoordF.y, CoordF.z);
1587				#if ( Attach>-0.1 )
1588					attach Attach
1589				#end
1590				#local Force=fn_Force(CoordF.x, CoordF.y, CoordF.z);
1591				#if ( Force>-0.1 )
1592					force Force
1593				#end
1594			#end
1595		}
1596
1597		#local Cnt=Cnt+1;
1598	#end
1599
1600	#if (Faces)
1601
1602		#local Cnt=0;
1603
1604		#while (Cnt<Count)
1605
1606			#local Coord=<mod(Cnt, GridSize.x),
1607			              div(mod(Cnt, GridSize.x*GridSize.y), GridSize.x),
1608			              div(Cnt, GridSize.x*GridSize.y)>;
1609
1610			#local UpB=GridSize-1-EPS;
1611
1612			#if (((Coord.x<EPS)|(Coord.x>UpB.x))&
1613				    (Coord.y<UpB.y)&(Coord.z<UpB.z))  // ------ x-negative/positive Face ------
1614
1615				face { StIdx+Cnt, StIdx+Cnt+GridSize.x, StIdx+Cnt+GridSize.x*GridSize.y+GridSize.x }
1616				face { StIdx+Cnt, StIdx+Cnt+GridSize.x*GridSize.y+GridSize.x, StIdx+Cnt+GridSize.x*GridSize.y }
1617			#end
1618
1619			#if (((Coord.y<EPS)|(Coord.y>UpB.y))&
1620				    (Coord.x<UpB.x)&(Coord.z<UpB.z))  // ------ y-negative/positive Face ------
1621
1622				face { StIdx+Cnt, StIdx+Cnt+1, StIdx+Cnt+GridSize.x*GridSize.y+1 }
1623				face { StIdx+Cnt, StIdx+Cnt+GridSize.x*GridSize.y+1, StIdx+Cnt+GridSize.x*GridSize.y}
1624			#end
1625
1626			#if (((Coord.z<EPS)|(Coord.z>UpB.z))&
1627				    (Coord.x<UpB.x)&(Coord.y<UpB.y))  // ------ z-negative/positive Face ------
1628
1629				face { StIdx+Cnt, StIdx+Cnt+1, StIdx+Cnt+GridSize.x+1 }
1630				face { StIdx+Cnt, StIdx+Cnt+GridSize.x+1, StIdx+Cnt+GridSize.x }
1631			#end
1632
1633			#local Cnt=Cnt+1;
1634
1635		#end
1636	#end
1637
1638
1639	#if (Diagonal>0)
1640
1641		#if (VE_Accuracy>0)
1642			#local VE_Elem_Cnt=dimension_size(VE_Elements, 1);
1643		#else
1644			#local VE_Elem_Cnt=0;
1645		#end
1646
1647		#local Cnt=0;
1648
1649		#while (Cnt<Count)
1650
1651			#local Coord=<mod(Cnt, GridSize.x),
1652			              div(mod(Cnt, GridSize.x*GridSize.y), GridSize.x),
1653			              div(Cnt, GridSize.x*GridSize.y)>;
1654
1655			#local CoordF=<Coord.x/(GridSize.x-1),
1656			               Coord.y/(GridSize.y-1),
1657			               Coord.z/(GridSize.z-1)>;
1658
1659			#local Stiffness=fn_Stiffness(CoordF.x, CoordF.y, CoordF.z);
1660			#local Damping=fn_Damping(CoordF.x, CoordF.y, CoordF.z);
1661
1662			#if (Coord.x<GridSize.x-1)
1663
1664				#if (VE_Elem_Cnt=0)
1665					connection {
1666						StIdx+Cnt, StIdx+Cnt+1
1667						stiffness Stiffness*Connect_Arr[0]
1668						damping Damping*Connect_Arr[0]
1669					}
1670				#else
1671					viscoelastic {
1672						StIdx+Cnt, StIdx+Cnt+1 stiffness Stiffness*Connect_Arr[0]
1673
1674						#local ECnt=0;
1675
1676						#while (ECnt<VE_Elem_Cnt)
1677							element { VE_Elements[ECnt][0]*Connect_Arr[0], VE_Elements[ECnt][1]*Connect_Arr[0] }
1678							#local ECnt=ECnt+1;
1679						#end
1680					}
1681				#end
1682
1683				#if (Diagonal>1)
1684					#if (Coord.y<GridSize.y-1)
1685
1686						#if (VE_Elem_Cnt=0)
1687							connection {
1688								StIdx+Cnt, StIdx+Cnt+GridSize.x+1
1689								stiffness Stiffness*Connect_Arr[1]
1690								damping Damping*Connect_Arr[1]
1691							}
1692						#else
1693							viscoelastic {
1694								StIdx+Cnt, StIdx+Cnt+GridSize.x+1 stiffness Stiffness*Connect_Arr[1]
1695
1696								#local ECnt=0;
1697
1698								#while (ECnt<VE_Elem_Cnt)
1699									element { VE_Elements[ECnt][0]*Connect_Arr[1], VE_Elements[ECnt][1]*Connect_Arr[1] }
1700									#local ECnt=ECnt+1;
1701								#end
1702							}
1703						#end
1704
1705						#if (Diagonal>2)
1706
1707							#if (VE_Elem_Cnt=0)
1708								connection {
1709									StIdx+Cnt+1, StIdx+Cnt+GridSize.x
1710									stiffness Stiffness*Connect_Arr[2]
1711									damping Damping*Connect_Arr[2]
1712								}
1713							#else
1714								viscoelastic {
1715									StIdx+Cnt+1, StIdx+Cnt+GridSize.x stiffness Stiffness*Connect_Arr[2]
1716
1717									#local ECnt=0;
1718
1719									#while (ECnt<VE_Elem_Cnt)
1720										element { VE_Elements[ECnt][0]*Connect_Arr[2], VE_Elements[ECnt][1]*Connect_Arr[2] }
1721										#local ECnt=ECnt+1;
1722									#end
1723								}
1724							#end
1725
1726						#end
1727					#end
1728				#end
1729			#end
1730			#if (Coord.y<GridSize.y-1)
1731
1732				#if (VE_Elem_Cnt=0)
1733					connection {
1734						StIdx+Cnt, StIdx+Cnt+GridSize.x
1735						stiffness Stiffness*Connect_Arr[0]
1736						damping Damping*Connect_Arr[0]
1737					}
1738				#else
1739					viscoelastic {
1740						StIdx+Cnt, StIdx+Cnt+GridSize.x stiffness Stiffness*Connect_Arr[0]
1741
1742						#local ECnt=0;
1743
1744						#while (ECnt<VE_Elem_Cnt)
1745							element { VE_Elements[ECnt][0]*Connect_Arr[0], VE_Elements[ECnt][1]*Connect_Arr[0] }
1746							#local ECnt=ECnt+1;
1747						#end
1748					}
1749				#end
1750
1751				#if (Diagonal>1)
1752					#if (Coord.z<GridSize.z-1)
1753
1754						#if (VE_Elem_Cnt=0)
1755							connection {
1756								StIdx+Cnt, StIdx+Cnt+GridSize.x*(GridSize.y+1)
1757								stiffness Stiffness*Connect_Arr[1]
1758								damping Damping*Connect_Arr[1]
1759							}
1760						#else
1761							viscoelastic {
1762								StIdx+Cnt, StIdx+Cnt+GridSize.x*(GridSize.y+1) stiffness Stiffness*Connect_Arr[1]
1763
1764								#local ECnt=0;
1765
1766								#while (ECnt<VE_Elem_Cnt)
1767									element { VE_Elements[ECnt][0]*Connect_Arr[1], VE_Elements[ECnt][1]*Connect_Arr[1] }
1768									#local ECnt=ECnt+1;
1769								#end
1770							}
1771						#end
1772
1773						#if (Diagonal>2)
1774
1775							#if (VE_Elem_Cnt=0)
1776								connection {
1777									StIdx+Cnt+GridSize.x, StIdx+Cnt+GridSize.x*GridSize.y
1778									stiffness Stiffness*Connect_Arr[2]
1779									damping Damping*Connect_Arr[2]
1780								}
1781							#else
1782								viscoelastic {
1783									StIdx+Cnt+GridSize.x, StIdx+Cnt+GridSize.x*GridSize.y stiffness Stiffness*Connect_Arr[2]
1784
1785									#local ECnt=0;
1786
1787									#while (ECnt<VE_Elem_Cnt)
1788										element { VE_Elements[ECnt][0]*Connect_Arr[2], VE_Elements[ECnt][1]*Connect_Arr[2] }
1789										#local ECnt=ECnt+1;
1790									#end
1791								}
1792							#end
1793
1794						#end
1795					#end
1796				#end
1797			#end
1798			#if (Coord.z<GridSize.z-1)
1799
1800				#if (VE_Elem_Cnt=0)
1801					connection {
1802						StIdx+Cnt, StIdx+Cnt+GridSize.x*GridSize.y
1803						stiffness Stiffness*Connect_Arr[0]
1804						damping Damping*Connect_Arr[0]
1805					}
1806				#else
1807					viscoelastic {
1808						StIdx+Cnt, StIdx+Cnt+GridSize.x*GridSize.y stiffness Stiffness*Connect_Arr[0]
1809
1810						#local ECnt=0;
1811
1812						#while (ECnt<VE_Elem_Cnt)
1813							element { VE_Elements[ECnt][0]*Connect_Arr[0], VE_Elements[ECnt][1]*Connect_Arr[0] }
1814							#local ECnt=ECnt+1;
1815						#end
1816					}
1817				#end
1818
1819				#if (Diagonal>1)
1820					#if (Coord.x<GridSize.x-1)
1821
1822						#if (VE_Elem_Cnt=0)
1823							connection {
1824								StIdx+Cnt, StIdx+Cnt+GridSize.x*GridSize.y+1
1825								stiffness Stiffness*Connect_Arr[1]
1826								damping Damping*Connect_Arr[1]
1827							}
1828						#else
1829							viscoelastic {
1830								StIdx+Cnt, StIdx+Cnt+GridSize.x*GridSize.y+1 stiffness Stiffness*Connect_Arr[1]
1831
1832								#local ECnt=0;
1833
1834								#while (ECnt<VE_Elem_Cnt)
1835									element { VE_Elements[ECnt][0]*Connect_Arr[1], VE_Elements[ECnt][1]*Connect_Arr[1] }
1836									#local ECnt=ECnt+1;
1837								#end
1838							}
1839						#end
1840
1841						#if (Diagonal>2)
1842
1843							#if (VE_Elem_Cnt=0)
1844								connection {
1845									StIdx+Cnt+1, StIdx+Cnt+GridSize.x*GridSize.y
1846									stiffness Stiffness*Connect_Arr[2]
1847									damping Damping*Connect_Arr[2]
1848								}
1849							#else
1850								viscoelastic {
1851									StIdx+Cnt+1, StIdx+Cnt+GridSize.x*GridSize.y stiffness Stiffness*Connect_Arr[2]
1852
1853									#local ECnt=0;
1854
1855									#while (ECnt<VE_Elem_Cnt)
1856										element { VE_Elements[ECnt][0]*Connect_Arr[2], VE_Elements[ECnt][1]*Connect_Arr[2] }
1857										#local ECnt=ECnt+1;
1858									#end
1859								}
1860							#end
1861
1862						#end
1863					#end
1864				#end
1865			#end
1866
1867			#if (Diagonal>3)
1868				#if ((Coord.x<GridSize.x-1) &
1869					   (Coord.y<GridSize.y-1) &
1870					   (Coord.z<GridSize.z-1))
1871
1872					#if (VE_Elem_Cnt=0)
1873						connection {
1874							StIdx+Cnt, StIdx+Cnt+GridSize.x*(GridSize.y+1)+1
1875							stiffness Stiffness*Connect_Arr[3]
1876							damping Damping*Connect_Arr[3]
1877						}
1878						connection {
1879							StIdx+Cnt+1, StIdx+Cnt+GridSize.x*(GridSize.y+1)
1880							stiffness Stiffness*Connect_Arr[3]
1881							damping Damping*Connect_Arr[3]
1882						}
1883						connection {
1884							StIdx+Cnt+GridSize.x, StIdx+Cnt+GridSize.x*GridSize.y+1
1885							stiffness Stiffness*Connect_Arr[3]
1886							damping Damping*Connect_Arr[3]
1887						}
1888						connection {
1889							StIdx+Cnt+GridSize.x+1, StIdx+Cnt+GridSize.x*GridSize.y
1890							stiffness Stiffness*Connect_Arr[3]
1891							damping Damping*Connect_Arr[3]
1892						}
1893					#else
1894						viscoelastic {
1895							StIdx+Cnt, StIdx+Cnt+GridSize.x*(GridSize.y+1)+1 stiffness Stiffness*Connect_Arr[3]
1896
1897							#local ECnt=0;
1898
1899							#while (ECnt<VE_Elem_Cnt)
1900								element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
1901								#local ECnt=ECnt+1;
1902							#end
1903						}
1904						viscoelastic {
1905							StIdx+Cnt+1, StIdx+Cnt+GridSize.x*(GridSize.y+1) stiffness Stiffness*Connect_Arr[3]
1906
1907							#local ECnt=0;
1908
1909							#while (ECnt<VE_Elem_Cnt)
1910								element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
1911								#local ECnt=ECnt+1;
1912							#end
1913						}
1914						viscoelastic {
1915							StIdx+Cnt+GridSize.x, StIdx+Cnt+GridSize.x*GridSize.y+1 stiffness Stiffness*Connect_Arr[3]
1916
1917							#local ECnt=0;
1918
1919							#while (ECnt<VE_Elem_Cnt)
1920								element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
1921								#local ECnt=ECnt+1;
1922							#end
1923						}
1924						viscoelastic {
1925							StIdx+Cnt+GridSize.x+1, StIdx+Cnt+GridSize.x*GridSize.y stiffness Stiffness*Connect_Arr[3]
1926
1927							#local ECnt=0;
1928
1929							#while (ECnt<VE_Elem_Cnt)
1930								element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
1931								#local ECnt=ECnt+1;
1932							#end
1933						}
1934					#end
1935
1936				#end
1937			#end
1938
1939			#local Cnt=Cnt+1;
1940		#end
1941	#end
1942
1943	#debug "Done\n"
1944
1945#end
1946
1947// =======================================================================================
1948//  MechSim_Generate_Grid_Fn() macro
1949//
1950//  topology generation macro building a 3D grid of masses connected and with optional
1951//  faces on the outside.  density, stiffness and damping can be controlled by functions
1952//  functions also control fixed and attached masses
1953//
1954//  Parameters:
1955//      Velocity     - vector defining the common starting velocity of all masses.
1956//      Radius       - radius of all masses.
1957//      fn_Density   - user defined function controlling the density of the masses.
1958//                     x, y and z are evaluated in [0..1] range.
1959//      fn_Stiffness - user defined function controlling the stiffness of the connections.
1960//      fn_Damping   - user defined function controlling the damping of the connections.
1961//      Faces        - Boolean value controlling whether faces are generated for the surface.
1962//                     If true faces are generated on the outside shape.
1963//      Cube_Scale   - 3D vector controlling the distances in the grid. It defines the size of an elementary cell.
1964//      Grid_Size    - 3D vector containing the number of masses in all three directions.
1965//      Transf       - Transform applied to the mass positions
1966//      fn_Fixed     - user defined function controlling which masses are fixed.
1967//									   x, y and z are evaluated in [0..1] range. For function values > 0 the masses are fixed.
1968//      fn_Attach    - user defined function controlling which masses are attached.
1969//                     x, y and z are evaluated in [0..1] range. The function value determines the attachment index.
1970//      fn_Force     - user defined function controlling custom forces.
1971//                     x, y and z are evaluated in [0..1] range. The function value determines the custom force index.
1972//      Connect_Arr  - Array containing weights for connection stiffness and damping.
1973//
1974// =======================================================================================
1975#macro MechSim_Generate_Grid_Fn(Velocity, Radius, fn_Density, fn_Stiffness, fn_Damping, Faces, Cube_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr)
1976
1977	#local VE_Elements=array[1]
1978	#local VE_Accuracy=0;
1979
1980	MechSim_Generate_Grid_X(
1981		Velocity, Radius, fn_Density, fn_Stiffness, fn_Damping, VE_Elements, VE_Accuracy, Faces, Cube_Scale, Grid_Size,
1982		Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr
1983	)
1984
1985#end
1986
1987// =======================================================================================
1988//  MechSim_Generate_Grid_Fn_VE() macro
1989//
1990//  variant of MechSim_Generate_Grid_Fn() generating viscoelastic connections
1991//
1992//  Parameters:
1993//      Velocity     - vector defining the common starting velocity of all masses.
1994//      Radius       - radius of all masses.
1995//      fn_Density   - user defined function controlling the density of the masses.
1996//                     x, y and z are evaluated in [0..1] range.
1997//      fn_Stiffness - user defined function controlling the stiffness of the connections.
1998//      VE_Elements  - array with the parameters for viscoelastic connections
1999//      VE_Accuracy  - accuracy value for viscoelastic connection
2000//      Faces        - Boolean value controlling whether faces are generated for the surface.
2001//                     If true faces are generated on the outside shape.
2002//      Cube_Scale   - 3D vector controlling the distances in the grid. It defines the size of an elementary cell.
2003//      Grid_Size    - 3D vector containing the number of masses in all three directions.
2004//      Transf       - Transform applied to the mass positions
2005//      fn_Fixed     - user defined function controlling which masses are fixed.
2006//									   x, y and z are evaluated in [0..1] range. For function values > 0 the masses are fixed.
2007//      fn_Attach    - user defined function controlling which masses are attached.
2008//                     x, y and z are evaluated in [0..1] range. The function value determines the attachment index.
2009//      fn_Force     - user defined function controlling custom forces.
2010//                     x, y and z are evaluated in [0..1] range. The function value determines the custom force index.
2011//      Connect_Arr  - Array containing weights for connection stiffness and damping.
2012//
2013// =======================================================================================
2014#macro MechSim_Generate_Grid_Fn_VE(Velocity, Radius, fn_Density, fn_Stiffness, VE_Elements, VE_Accuracy, Faces, Cube_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr)
2015
2016	#local __MSIM_fn_Damping=function(x, y, z) {0}
2017
2018	MechSim_Generate_Grid_X(
2019		Velocity, Radius, fn_Density, fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy, Faces, Cube_Scale, Grid_Size,
2020		Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr
2021	)
2022
2023#end
2024
2025// =======================================================================================
2026//  MechSim_Generate_Grid() macro
2027//
2028//  topology generation macro building a 3D grid of masses connected and with optional
2029//  faces on the outside.  density, stiffness and damping as fixed values,
2030//  masses are not fixed or attached.
2031//
2032//  Parameters:
2033//      Velocity    - common velocity of all masses
2034//      Radius      - radius of the masses
2035//      Density     - density of the masses
2036//      Stiffness   - stiffness of the connections
2037//      Damping     - damping of the connections
2038//      Faces       - Boolean value controlling whether faces are generated for the
2039//                    surface.
2040//      Cube_Scale  - Grid distance vector, defining the size of an elemetary
2041//                    cell in the grid.
2042//      Grid_Size   - Vector with number of masses in x, y and z direction
2043//      Transf      - Transform applied to the mass positions
2044//      Connect_Arr - Array containing weights for connection stiffness and damping
2045//
2046// =======================================================================================
2047#macro MechSim_Generate_Grid(Velocity, Radius, Density, Stiffness, Damping, Faces, Cube_Scale, Grid_Size, Transf, Connect_Arr)
2048
2049	#local __MSIM_fn_Density=function(x, y, z) {Density}
2050	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2051	#local __MSIM_fn_Damping=function(x, y, z) {Damping}
2052	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2053	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2054	#local __MSIM_fn_Force=function(x, y, z) {-1}
2055
2056	#local VE_Elements=array[1]
2057	#local VE_Accuracy=0;
2058
2059	MechSim_Generate_Grid_X(
2060		Velocity, Radius, __MSIM_fn_Density,
2061		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2062		Faces, Cube_Scale, Grid_Size,
2063		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2064	)
2065
2066#end
2067
2068// =======================================================================================
2069//  MechSim_Generate_Grid_VE() macro
2070//
2071//  variant of MechSim_Generate_Grid() generating viscoelastic connections
2072//
2073//  Parameters:
2074//      Velocity    - common velocity of all masses
2075//      Radius      - radius of the masses
2076//      Density     - density of the masses
2077//      Stiffness   - stiffness of the connections
2078//      VE_Elements - array with the parameters for viscoelastic connections
2079//      VE_Accuracy - accuracy value for viscoelastic connection
2080//      Faces       - Boolean value controlling whether faces are generated for the
2081//                    surface.
2082//      Cube_Scale  - Grid distance vector, defining the size of an elemetary
2083//                    cell in the grid.
2084//      Grid_Size   - Vector with number of masses in x, y and z direction
2085//      Transf      - Transform applied to the mass positions
2086//      Connect_Arr - Array containing weights for connection stiffness and damping
2087//
2088// =======================================================================================
2089#macro MechSim_Generate_Grid_VE(Velocity, Radius, Density, Stiffness, VE_Elements, VE_Accuracy, Faces, Cube_Scale, Grid_Size, Transf, Connect_Arr)
2090
2091	#local __MSIM_fn_Density=function(x, y, z) {Density}
2092	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2093	#local __MSIM_fn_Damping=function(x, y, z) {0}
2094	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2095	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2096	#local __MSIM_fn_Force=function(x, y, z) {-1}
2097
2098	MechSim_Generate_Grid_X(
2099		Velocity, Radius, __MSIM_fn_Density,
2100		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2101		Faces, Cube_Scale, Grid_Size,
2102		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2103	)
2104
2105#end
2106
2107// =======================================================================================
2108//  MechSim_Generate_Grid_Std() macro
2109//
2110//  topology generation macro building a 3D grid of masses connected and with optional
2111//  faces on the outside.  density, stiffness and damping as fixed values,
2112//  masses are not fixed or attached.
2113//  Instead of the connection weight array a Diagonal parameter is used
2114//
2115//  Parameters:
2116//      Velocity    - common velocity of all masses
2117//      Radius      - radius of the masses
2118//      Density     - density of the masses
2119//      Stiffness   - stiffness of the connections
2120//      Damping     - damping of the connections
2121//      Faces       - Boolean value controlling whether faces are generated for the
2122//                    surface.
2123//      Cube_Scale  - Grid distance vector, defining the size of an elemetary
2124//                    cell in the grid.
2125//      Grid_Size   - Vector with number of masses in x, y and z direction
2126//      Transf      - Transform applied to the mass positions
2127//      Diagonal   - controling which diagonal connections are generated in the grid.
2128//
2129// =======================================================================================
2130#macro MechSim_Generate_Grid_Std(Velocity, Radius, Density, Stiffness, Damping, Faces, Cube_Scale, Grid_Size, Transf, Diagonal)
2131
2132	#local __MSIM_fn_Density=function(x, y, z) {Density}
2133	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2134	#local __MSIM_fn_Damping=function(x, y, z) {Damping}
2135	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2136	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2137	#local __MSIM_fn_Force=function(x, y, z) {-1}
2138
2139	#local VE_Elements=array[1]
2140	#local VE_Accuracy=0;
2141
2142	#local Connect_Arr=array[max(1, Diagonal)]
2143
2144	#local Cnt=0;
2145	#while (Cnt<max(1, Diagonal))
2146		#local Connect_Arr[Cnt]=1;
2147		#local Cnt=Cnt+1;
2148	#end
2149
2150	#if (Diagonal=0)
2151		#local Connect_Arr[0]=0;
2152	#end
2153
2154	MechSim_Generate_Grid_X(
2155		Velocity, Radius, __MSIM_fn_Density,
2156		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2157		Faces, Cube_Scale, Grid_Size,
2158		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2159	)
2160
2161#end
2162
2163// =======================================================================================
2164//  MechSim_Generate_Grid_Std_VE() macro
2165//
2166//  variant of MechSim_Generate_Grid_Std() generating viscoelastic connections
2167//
2168//  Parameters:
2169//      Velocity    - common velocity of all masses
2170//      Radius      - radius of the masses
2171//      Density     - density of the masses
2172//      Stiffness   - stiffness of the connections
2173//      VE_Elements - array with the parameters for viscoelastic connections
2174//      VE_Accuracy - accuracy value for viscoelastic connection
2175//      Faces       - Boolean value controlling whether faces are generated for the
2176//                    surface.
2177//      Cube_Scale  - Grid distance vector, defining the size of an elemetary
2178//                    cell in the grid.
2179//      Grid_Size   - Vector with number of masses in x, y and z direction
2180//      Transf      - Transform applied to the mass positions
2181//      Diagonal   - controling which diagonal connections are generated in the grid.
2182//
2183// =======================================================================================
2184#macro MechSim_Generate_Grid_Std_VE(Velocity, Radius, Density, Stiffness, VE_Elements, VE_Accuracy, Faces, Cube_Scale, Grid_Size, Transf, Diagonal)
2185
2186	#local __MSIM_fn_Density=function(x, y, z) {Density}
2187	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2188	#local __MSIM_fn_Damping=function(x, y, z) {0}
2189	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2190	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2191	#local __MSIM_fn_Force=function(x, y, z) {-1}
2192
2193	#local Connect_Arr=array[max(1, Diagonal)]
2194
2195	#local Cnt=0;
2196	#while (Cnt<max(1, Diagonal))
2197		#local Connect_Arr[Cnt]=1;
2198		#local Cnt=Cnt+1;
2199	#end
2200
2201	#if (Diagonal=0)
2202		#local Connect_Arr[0]=0;
2203	#end
2204
2205	MechSim_Generate_Grid_X(
2206		Velocity, Radius, __MSIM_fn_Density,
2207		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2208		Faces, Cube_Scale, Grid_Size,
2209		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2210	)
2211
2212#end
2213
2214// =======================================================================================
2215//  MechSim_Generate_Box() macro
2216//
2217//  topology generation macro building a 3D grid of masses connected and with optional
2218//  faces on the outside.  Mass of the whole body given.
2219//
2220//  Parameters:
2221//      Velocity   - common velocity of all masses
2222//      Radius     - radius of the masses
2223//      Mass       - mass of the whole body
2224//      Stiffness  - stiffness of the connections
2225//      Damping    - damping of the connections
2226//      Faces      - Boolean value controlling whether faces are generated for the
2227//                   surface.
2228//      Cube_Scale - Grid distance vector, defining the size of an elemetary
2229//                   cell in the grid.
2230//      Grid_Size  - Vector with number of masses in x, y and z direction
2231//      Transf     - Transform applied to the mass positions
2232//      Diagonal   - controling which diagonal connections are generated in the grid.
2233//
2234// =======================================================================================
2235#macro MechSim_Generate_Box(Velocity, Radius, Mass, Stiffness, Damping, Faces, Cube_Scale, Grid_Size, Transf, Diagonal)
2236
2237	#local Density=(Mass/(Grid_Size.x*Grid_Size.y*Grid_Size.z))/((4/3)*pi*pow(Radius,3));
2238
2239	#local __MSIM_fn_Density=function(x, y, z) {Density}
2240	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2241	#local __MSIM_fn_Damping=function(x, y, z) {Damping}
2242	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2243	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2244	#local __MSIM_fn_Force=function(x, y, z) {-1}
2245
2246	#local VE_Elements=array[1]
2247	#local VE_Accuracy=0;
2248
2249	#local Connect_Arr=array[max(1, Diagonal)]
2250
2251	#local Cnt=0;
2252	#while (Cnt<max(1, Diagonal))
2253		#local Connect_Arr[Cnt]=1;
2254		#local Cnt=Cnt+1;
2255	#end
2256
2257	#if (Diagonal=0)
2258		#local Connect_Arr[0]=0;
2259	#end
2260
2261	MechSim_Generate_Grid_X(
2262		Velocity, Radius, __MSIM_fn_Density,
2263		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2264		Faces, Cube_Scale, Grid_Size,
2265		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2266	)
2267
2268#end
2269
2270// =======================================================================================
2271//  MechSim_Generate_Box_VE() macro
2272//
2273//  variant of MechSim_Generate_Box() generating viscoelastic connections
2274//
2275//  Parameters:
2276//      Velocity   - common velocity of all masses
2277//      Radius     - radius of the masses
2278//      Mass       - mass of the whole body
2279//      Stiffness  - stiffness of the connections
2280//      VE_Elements - array with the parameters for viscoelastic connections
2281//      VE_Accuracy - accuracy value for viscoelastic connection
2282//      Faces      - Boolean value controlling whether faces are generated for the
2283//                   surface.
2284//      Cube_Scale - Grid distance vector, defining the size of an elemetary
2285//                   cell in the grid.
2286//      Grid_Size  - Vector with number of masses in x, y and z direction
2287//      Transf     - Transform applied to the mass positions
2288//      Diagonal   - controling which diagonal connections are generated in the grid.
2289//
2290// =======================================================================================
2291#macro MechSim_Generate_Box_VE(Velocity, Radius, Mass, Stiffness, VE_Elements, VE_Accuracy, Faces, Cube_Scale, Grid_Size, Transf, Diagonal)
2292
2293	#local Density=(Mass/(Grid_Size.x*Grid_Size.y*Grid_Size.z))/((4/3)*pi*pow(Radius,3));
2294
2295	#local __MSIM_fn_Density=function(x, y, z) {Density}
2296	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2297	#local __MSIM_fn_Damping=function(x, y, z) {0}
2298	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2299	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2300	#local __MSIM_fn_Force=function(x, y, z) {-1}
2301
2302	#local Connect_Arr=array[max(1, Diagonal)]
2303
2304	#local Cnt=0;
2305	#while (Cnt<max(1, Diagonal))
2306		#local Connect_Arr[Cnt]=1;
2307		#local Cnt=Cnt+1;
2308	#end
2309
2310	#if (Diagonal=0)
2311		#local Connect_Arr[0]=0;
2312	#end
2313
2314	MechSim_Generate_Grid_X(
2315		Velocity, Radius, __MSIM_fn_Density,
2316		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2317		Faces, Cube_Scale, Grid_Size,
2318		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2319	)
2320
2321#end
2322
2323// =======================================================================================
2324//  MechSim_Generate_Block() macro
2325//
2326//  topology generation macro building a 3D grid of masses connected and with optional
2327//  faces on the outside.  Mass of the whole body given. Instead of
2328//  a Cube_Scale parameter two corner points are given.
2329//
2330//  Parameters:
2331//      Velocity   - common velocity of all masses
2332//      Radius     - radius of the masses
2333//      Mass       - mass of the whole body
2334//      Stiffness  - stiffness of the connections
2335//      Damping    - damping of the connections
2336//      Faces      - Boolean value controlling whether faces are generated for the
2337//                   surface.
2338//      Start, End - Corner coordinates of the grid to generate
2339//      Grid_Size  - Vector with number of masses in x, y and z direction
2340//      Transf     - Transform applied to the mass positions
2341//      Diagonal   - controling which diagonal connections are generated in the grid.
2342//
2343// =======================================================================================
2344#macro MechSim_Generate_Block(Velocity, Radius, Mass, Stiffness, Damping, Faces, Start, End, Grid_Size, Transf, Diagonal)
2345
2346	#local Density=(Mass/(Grid_Size.x*Grid_Size.y*Grid_Size.z))/((4/3)*pi*pow(Radius,3));
2347
2348	#local __MSIM_fn_Density=function(x, y, z) {Density}
2349	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2350	#local __MSIM_fn_Damping=function(x, y, z) {Damping}
2351	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2352	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2353	#local __MSIM_fn_Force=function(x, y, z) {-1}
2354
2355	#local VE_Elements=array[1]
2356	#local VE_Accuracy=0;
2357
2358	#local Connect_Arr=array[max(1, Diagonal)]
2359
2360	#local Cnt=0;
2361	#while (Cnt<max(1, Diagonal))
2362		#local Connect_Arr[Cnt]=1;
2363		#local Cnt=Cnt+1;
2364	#end
2365
2366	#if (Diagonal=0)
2367		#local Connect_Arr[0]=0;
2368	#end
2369
2370  #local Cube_Scale=<1/(Grid_Size.x-1),1/(Grid_Size.y-1),1/(Grid_Size.z-1)>;
2371	#local Pnt1=Start+<0,0,0>;
2372	#local Pnt2=End+<0,0,0>;
2373
2374	#local Transf2=
2375		transform {
2376			scale (Pnt2-Pnt1)
2377			translate Pnt1
2378			transform { Transf }
2379		}
2380
2381	MechSim_Generate_Grid_X(
2382		Velocity, Radius, __MSIM_fn_Density,
2383		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2384		Faces, Cube_Scale, Grid_Size,
2385		Transf2, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2386	)
2387
2388#end
2389
2390// =======================================================================================
2391//  MechSim_Generate_Block_VE() macro
2392//
2393//  variant of MechSim_Generate_Block() generating viscoelastic connections
2394//
2395//  Parameters:
2396//      Velocity   - common velocity of all masses
2397//      Radius     - radius of the masses
2398//      Mass       - mass of the whole body
2399//      Stiffness  - stiffness of the connections
2400//      VE_Elements - array with the parameters for viscoelastic connections
2401//      VE_Accuracy - accuracy value for viscoelastic connection
2402//      Faces      - Boolean value controlling whether faces are generated for the
2403//                   surface.
2404//      Start, End - Corner coordinates of the grid to generate
2405//      Grid_Size  - Vector with number of masses in x, y and z direction
2406//      Transf     - Transform applied to the mass positions
2407//      Diagonal   - controling which diagonal connections are generated in the grid.
2408//
2409// =======================================================================================
2410#macro MechSim_Generate_Block_VE(Velocity, Radius, Mass, Stiffness, VE_Elements, VE_Accuracy, Faces, Start, End, Grid_Size, Transf, Diagonal)
2411
2412	#local Density=(Mass/(Grid_Size.x*Grid_Size.y*Grid_Size.z))/((4/3)*pi*pow(Radius,3));
2413
2414	#local __MSIM_fn_Density=function(x, y, z) {Density}
2415	#local __MSIM_fn_Stiffness=function(x, y, z) {Stiffness}
2416	#local __MSIM_fn_Damping=function(x, y, z) {0}
2417	#local __MSIM_fn_Fixed=function(x, y, z) {-1}
2418	#local __MSIM_fn_Attach=function(x, y, z) {-1}
2419	#local __MSIM_fn_Force=function(x, y, z) {-1}
2420
2421	#local Connect_Arr=array[max(1, Diagonal)]
2422
2423	#local Cnt=0;
2424	#while (Cnt<max(1, Diagonal))
2425		#local Connect_Arr[Cnt]=1;
2426		#local Cnt=Cnt+1;
2427	#end
2428
2429	#if (Diagonal=0)
2430		#local Connect_Arr[0]=0;
2431	#end
2432
2433  #local Cube_Scale=<1/(Grid_Size.x-1),1/(Grid_Size.y-1),1/(Grid_Size.z-1)>;
2434	#local Pnt1=Start+<0,0,0>;
2435	#local Pnt2=End+<0,0,0>;
2436
2437	#local Transf2=
2438		transform {
2439			scale (Pnt2-Pnt1)
2440			translate Pnt1
2441			transform { Transf }
2442		}
2443
2444	MechSim_Generate_Grid_X(
2445		Velocity, Radius, __MSIM_fn_Density,
2446		__MSIM_fn_Stiffness, __MSIM_fn_Damping, VE_Elements, VE_Accuracy,
2447		Faces, Cube_Scale, Grid_Size,
2448		Transf2, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
2449	)
2450
2451#end
2452
2453// #######################################################################################
2454//   Patch topology generation macros
2455// #######################################################################################
2456
2457// =======================================================================================
2458//  MechSim_Generate_Patch_X() macro
2459//
2460//  basis macro for generating 2D grid (patch) topologies.
2461//  Do not use this but the wrapper macros below.
2462//
2463//  Parameters:
2464//      Velocity    - common velocity of all masses
2465//      Radius      - radius of the masses
2466//      Density     - density of the masses
2467//      Stiffness   - stiffness of the connections
2468//      Damping     - damping of the connections
2469//      VE_Elements - array with the parameters for viscoelastic connections
2470//      VE_Accuracy - accuracy value for viscoelastic connections -
2471//                    <= 0 means to create normal connections
2472//      Faces       - Boolean value controlling whether faces are generated for the
2473//                    surface.
2474//      Rect_Scale  - 2D Grid distance vector, defining the size of an elemetary
2475//                    rectangle in the grid.
2476//      Grid_Size   - 2D Vector with number of masses in x and y direction
2477//      Transf      - Transform applied to the mass positions
2478//      fn_Fixed    - user defined function controlling which masses are fixed.
2479//									  x and y are evaluated in [0..1] range. For function values > 0 the masses are fixed.
2480//      fn_Attach   - user defined function controlling which masses are fixed.
2481//                    x and y are evaluated in [0..1] range. The function value determines the attachment index.
2482//      fn_Force     - user defined function controlling custom forces.
2483//                    x and y are evaluated in [0..1] range. The function value determines the custom force index.
2484//      Connect_Arr - Array containing weights for connection stiffness and damping
2485//
2486// =======================================================================================
2487#macro MechSim_Generate_Patch_X(Velocity, Radius, Density, Stiffness, Damping, VE_Elements, VE_Accuracy, Faces, Rect_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr)
2488
2489	#debug "Generating Patch..."
2490
2491	#local Vel=Velocity+<0,0,0>;
2492	#local CubeScale=Rect_Scale+<0,0,0>;
2493	#local GridSize=Grid_Size+<0,0,0>;
2494
2495	#local EPS=0.001*CubeScale.x;
2496
2497	#local StIdx=mechsim:mass_count;
2498	#local Count=(GridSize.x*GridSize.y);
2499	#local Con_Cnt=dimension_size(Connect_Arr, 1);
2500
2501	#local Cnt=0;
2502
2503	#while (Cnt<Count)
2504
2505		#local Coord=<mod(Cnt, GridSize.x),
2506		              div(Cnt, GridSize.x)>;
2507
2508
2509		#local Coord2=<Coord.x*CubeScale.x,
2510		               Coord.y*CubeScale.y, 0>;
2511
2512
2513		#local CoordF=<Coord.x/(GridSize.x-1),
2514		               Coord.y/(GridSize.y-1)>;
2515
2516		mass {
2517			vtransform(Coord2, Transf), Vel, Radius density Density
2518
2519			#if ( fn_Fixed(CoordF.x, CoordF.y, 0)>0 )
2520				fixed on
2521			#else
2522				#local Attach=fn_Attach(CoordF.x, CoordF.y, 0);
2523				#if ( Attach>-0.1 )
2524					attach Attach
2525				#end
2526				#local Force=fn_Force(CoordF.x, CoordF.y, 0);
2527				#if ( Force>-0.1 )
2528					force Force
2529				#end
2530			#end
2531		}
2532
2533		#local Cnt=Cnt+1;
2534	#end
2535
2536	#if (Faces)
2537
2538		#local Cnt=0;
2539
2540		#while (Cnt<Count)
2541
2542			#local Coord=<mod(Cnt, GridSize.x),
2543			              div(Cnt, GridSize.x)>;
2544
2545			#local UpB=GridSize-1-EPS;
2546
2547			#if ((Coord.x<UpB.x)&(Coord.y<UpB.y))
2548
2549				face { StIdx+Cnt, StIdx+Cnt+1, StIdx+Cnt+GridSize.x+1 }
2550				face { StIdx+Cnt, StIdx+Cnt+GridSize.x, StIdx+Cnt+GridSize.x+1 }
2551
2552			#end
2553
2554			#local Cnt=Cnt+1;
2555
2556		#end
2557	#end
2558
2559
2560	#if (Con_Cnt>0)
2561
2562		#if (VE_Accuracy>0)
2563			#local VE_Elem_Cnt=dimension_size(VE_Elements, 1);
2564		#else
2565			#local VE_Elem_Cnt=0;
2566		#end
2567
2568		#local Cnt=0;
2569
2570		#while (Cnt<Count)
2571
2572			#local Coord=<mod(Cnt, GridSize.x),
2573			              div(Cnt, GridSize.x)>;
2574
2575			#local UpB=GridSize-1-EPS;
2576
2577			#if (Coord.x<UpB.x)
2578
2579				#if (VE_Elem_Cnt=0)
2580					connection {
2581						StIdx+Cnt, StIdx+Cnt+1
2582						stiffness Stiffness*Connect_Arr[0]
2583						damping Damping*Connect_Arr[0]
2584						//length CubeScale.x
2585					}
2586				#else
2587					viscoelastic {
2588						StIdx+Cnt, StIdx+Cnt+1 stiffness Stiffness*Connect_Arr[0]
2589						accuracy VE_Accuracy
2590						//length CubeScale.x
2591
2592						#local ECnt=0;
2593
2594						#while (ECnt<VE_Elem_Cnt)
2595							element { VE_Elements[ECnt][0]*Connect_Arr[0], VE_Elements[ECnt][1]*Connect_Arr[0] }
2596							#local ECnt=ECnt+1;
2597						#end
2598					}
2599				#end
2600
2601			#end
2602			#if (Coord.y<UpB.y)
2603
2604				#if (VE_Elem_Cnt=0)
2605					connection {
2606						StIdx+Cnt, StIdx+Cnt+GridSize.x
2607						stiffness Stiffness*Connect_Arr[0]
2608						damping Damping*Connect_Arr[0]
2609						//length CubeScale.y
2610					}
2611				#else
2612					viscoelastic {
2613						StIdx+Cnt, StIdx+Cnt+GridSize.x stiffness Stiffness*Connect_Arr[0]
2614						accuracy VE_Accuracy
2615						//length CubeScale.y
2616
2617						#local ECnt=0;
2618
2619						#while (ECnt<VE_Elem_Cnt)
2620							element { VE_Elements[ECnt][0]*Connect_Arr[0], VE_Elements[ECnt][1]*Connect_Arr[0] }
2621							#local ECnt=ECnt+1;
2622						#end
2623					}
2624				#end
2625
2626			#end
2627
2628			#if (Con_Cnt>1)
2629				#if ((Coord.x<UpB.x)&(Coord.y<UpB.y))
2630
2631					#if (VE_Elem_Cnt=0)
2632						connection {
2633							StIdx+Cnt+GridSize.x, StIdx+Cnt+1
2634							stiffness Stiffness*Connect_Arr[1]
2635							damping Damping*Connect_Arr[1]
2636							//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2637						}
2638						connection {
2639							StIdx+Cnt, StIdx+Cnt+GridSize.x+1
2640							stiffness Stiffness*Connect_Arr[1]
2641							damping Damping*Connect_Arr[1]
2642							//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2643						}
2644					#else
2645						viscoelastic {
2646							StIdx+Cnt+GridSize.x, StIdx+Cnt+1 stiffness Stiffness*Connect_Arr[1]
2647							accuracy VE_Accuracy
2648							//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2649
2650							#local ECnt=0;
2651
2652							#while (ECnt<VE_Elem_Cnt)
2653								element { VE_Elements[ECnt][0]*Connect_Arr[1], VE_Elements[ECnt][1]*Connect_Arr[1] }
2654								#local ECnt=ECnt+1;
2655							#end
2656						}
2657						viscoelastic {
2658							StIdx+Cnt, StIdx+Cnt+GridSize.x+1 stiffness Stiffness*Connect_Arr[1]
2659							accuracy VE_Accuracy
2660							//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2661
2662							#local ECnt=0;
2663
2664							#while (ECnt<VE_Elem_Cnt)
2665								element { VE_Elements[ECnt][0]*Connect_Arr[1], VE_Elements[ECnt][1]*Connect_Arr[1] }
2666								#local ECnt=ECnt+1;
2667							#end
2668						}
2669					#end
2670
2671				#end
2672
2673				#if (Con_Cnt>2)
2674
2675					#local UpB2=GridSize-2-EPS;
2676
2677					#if (Coord.x<UpB2.x)
2678						#if (VE_Elem_Cnt=0)
2679							connection {
2680								StIdx+Cnt, StIdx+Cnt+2
2681								stiffness Stiffness*Connect_Arr[2]
2682								damping Damping*Connect_Arr[2]
2683								//length 2*CubeScale.x
2684							}
2685						#else
2686							viscoelastic {
2687								StIdx+Cnt, StIdx+Cnt+2 stiffness Stiffness*Connect_Arr[2]
2688								accuracy VE_Accuracy
2689								//length 2*CubeScale.x
2690
2691								#local ECnt=0;
2692
2693								#while (ECnt<VE_Elem_Cnt)
2694									element { VE_Elements[ECnt][0]*Connect_Arr[2], VE_Elements[ECnt][1]*Connect_Arr[2] }
2695									#local ECnt=ECnt+1;
2696								#end
2697							}
2698						#end
2699					#end
2700					#if (Coord.y<UpB2.y)
2701						#if (VE_Elem_Cnt=0)
2702							connection {
2703								StIdx+Cnt, StIdx+Cnt+GridSize.x*2
2704								stiffness Stiffness*Connect_Arr[2]
2705								damping Damping*Connect_Arr[2]
2706								//length 2*CubeScale.y
2707							}
2708						#else
2709							viscoelastic {
2710								StIdx+Cnt, StIdx+Cnt+GridSize.x*2 stiffness Stiffness*Connect_Arr[2]
2711								accuracy VE_Accuracy
2712								//length 2*CubeScale.y
2713
2714								#local ECnt=0;
2715
2716								#while (ECnt<VE_Elem_Cnt)
2717									element { VE_Elements[ECnt][0]*Connect_Arr[2], VE_Elements[ECnt][1]*Connect_Arr[2] }
2718									#local ECnt=ECnt+1;
2719								#end
2720							}
2721						#end
2722					#end
2723
2724					#if (Con_Cnt>3)
2725						#if ((Coord.x<UpB2.x)&(Coord.y<UpB.y))
2726							#if (VE_Elem_Cnt=0)
2727								connection {
2728									StIdx+Cnt+GridSize.x, StIdx+Cnt+2
2729									stiffness Stiffness*Connect_Arr[3]
2730									damping Damping*Connect_Arr[3]
2731									//length sqrt(CubeScale.x*CubeScale.x*4 + CubeScale.y*CubeScale.y)
2732								}
2733								connection {
2734									StIdx+Cnt, StIdx+Cnt+GridSize.x+2
2735									stiffness Stiffness*Connect_Arr[3]
2736									damping Damping*Connect_Arr[3]
2737									//length sqrt(CubeScale.x*CubeScale.x*4 + CubeScale.y*CubeScale.y)
2738								}
2739							#else
2740								viscoelastic {
2741									StIdx+Cnt+GridSize.x, StIdx+Cnt+2 stiffness Stiffness*Connect_Arr[3]
2742									accuracy VE_Accuracy
2743									//length sqrt(CubeScale.x*CubeScale.x*4 + CubeScale.y*CubeScale.y)
2744
2745									#local ECnt=0;
2746
2747									#while (ECnt<VE_Elem_Cnt)
2748										element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
2749										#local ECnt=ECnt+1;
2750									#end
2751								}
2752								viscoelastic {
2753									StIdx+Cnt, StIdx+Cnt+GridSize.x+2 stiffness Stiffness*Connect_Arr[3]
2754									accuracy VE_Accuracy
2755									//length sqrt(CubeScale.x*CubeScale.x*4 + CubeScale.y*CubeScale.y)
2756
2757									#local ECnt=0;
2758
2759									#while (ECnt<VE_Elem_Cnt)
2760										element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
2761										#local ECnt=ECnt+1;
2762									#end
2763								}
2764							#end
2765						#end
2766
2767						#if ((Coord.x<UpB.x)&(Coord.y<UpB2.y))
2768							#if (VE_Elem_Cnt=0)
2769								connection {
2770									StIdx+Cnt+GridSize.x*2, StIdx+Cnt+1
2771									stiffness Stiffness*Connect_Arr[3]
2772									damping Damping*Connect_Arr[3]
2773									//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y*4)
2774								}
2775								connection {
2776									StIdx+Cnt, StIdx+Cnt+GridSize.x*2+1
2777									stiffness Stiffness*Connect_Arr[3]
2778									damping Damping*Connect_Arr[3]
2779									//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y*4)
2780								}
2781							#else
2782								viscoelastic {
2783									StIdx+Cnt+GridSize.x*2, StIdx+Cnt+1 stiffness Stiffness*Connect_Arr[3]
2784									accuracy VE_Accuracy
2785									//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y*4)
2786
2787									#local ECnt=0;
2788
2789									#while (ECnt<VE_Elem_Cnt)
2790										element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
2791										#local ECnt=ECnt+1;
2792									#end
2793								}
2794								viscoelastic {
2795									StIdx+Cnt, StIdx+Cnt+GridSize.x*2+1 stiffness Stiffness*Connect_Arr[3]
2796									accuracy VE_Accuracy
2797									//length sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y*4)
2798
2799									#local ECnt=0;
2800
2801									#while (ECnt<VE_Elem_Cnt)
2802										element { VE_Elements[ECnt][0]*Connect_Arr[3], VE_Elements[ECnt][1]*Connect_Arr[3] }
2803										#local ECnt=ECnt+1;
2804									#end
2805								}
2806							#end
2807						#end
2808
2809						#if (Con_Cnt>4)
2810							#if ((Coord.x<UpB2.x)&(Coord.y<UpB2.y))
2811								#if (VE_Elem_Cnt=0)
2812									connection {
2813										StIdx+Cnt+GridSize.x*2, StIdx+Cnt+2
2814										stiffness Stiffness*Connect_Arr[4]
2815										damping Damping*Connect_Arr[4]
2816										//length 2*sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2817									}
2818									connection {
2819										StIdx+Cnt, StIdx+Cnt+GridSize.x*2+2
2820										stiffness Stiffness*Connect_Arr[4]
2821										damping Damping*Connect_Arr[4]
2822										//length 2*sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2823									}
2824								#else
2825									viscoelastic {
2826										StIdx+Cnt+GridSize.x*2, StIdx+Cnt+2 stiffness Stiffness*Connect_Arr[4]
2827										accuracy VE_Accuracy
2828										//length 2*sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2829
2830										#local ECnt=0;
2831
2832										#while (ECnt<VE_Elem_Cnt)
2833											element { VE_Elements[ECnt][0]*Connect_Arr[4], VE_Elements[ECnt][1]*Connect_Arr[4] }
2834											#local ECnt=ECnt+1;
2835										#end
2836									}
2837									viscoelastic {
2838										StIdx+Cnt, StIdx+Cnt+GridSize.x*2+2 stiffness Stiffness*Connect_Arr[4]
2839										accuracy VE_Accuracy
2840										//length 2*sqrt(CubeScale.x*CubeScale.x + CubeScale.y*CubeScale.y)
2841
2842										#local ECnt=0;
2843
2844										#while (ECnt<VE_Elem_Cnt)
2845											element { VE_Elements[ECnt][0]*Connect_Arr[4], VE_Elements[ECnt][1]*Connect_Arr[4] }
2846											#local ECnt=ECnt+1;
2847										#end
2848									}
2849								#end
2850							#end
2851
2852							#if (Con_Cnt>5)
2853
2854								#local UpB3=GridSize-3-EPS;
2855
2856								#if ((Coord.x<UpB3.x)&(Coord.y<UpB3.y))
2857									#if (VE_Elem_Cnt=0)
2858										connection {
2859											StIdx+Cnt, StIdx+Cnt+3
2860											stiffness Stiffness*Connect_Arr[5]
2861											damping Damping*Connect_Arr[5]
2862											//length 3*CubeScale.x
2863										}
2864										connection {
2865											StIdx+Cnt, StIdx+Cnt+GridSize.x*3
2866											stiffness Stiffness*Connect_Arr[5]
2867											damping Damping*Connect_Arr[5]
2868											//length 3*CubeScale.y
2869										}
2870									#else
2871										viscoelastic {
2872											StIdx+Cnt, StIdx+Cnt+3 stiffness Stiffness*Connect_Arr[5]
2873											accuracy VE_Accuracy
2874											//length 3*CubeScale.x
2875
2876											#local ECnt=0;
2877
2878											#while (ECnt<VE_Elem_Cnt)
2879												element { VE_Elements[ECnt][0]*Connect_Arr[5], VE_Elements[ECnt][1]*Connect_Arr[5] }
2880												#local ECnt=ECnt+1;
2881											#end
2882										}
2883										viscoelastic {
2884											StIdx+Cnt, StIdx+Cnt+GridSize.x*3 stiffness Stiffness*Connect_Arr[5]
2885											accuracy VE_Accuracy
2886											//length 3*CubeScale.y
2887
2888											#local ECnt=0;
2889
2890											#while (ECnt<VE_Elem_Cnt)
2891												element { VE_Elements[ECnt][0]*Connect_Arr[5], VE_Elements[ECnt][1]*Connect_Arr[5] }
2892												#local ECnt=ECnt+1;
2893											#end
2894										}
2895									#end
2896								#end
2897							#end /* Connect>5 */
2898						#end /* Connect>4 */
2899					#end /* Connect>3 */
2900				#end /* Connect>2 */
2901			#end /* Connect>1 */
2902
2903			#local Cnt=Cnt+1;
2904
2905		#end
2906
2907	#end /* Connect>0 */
2908
2909	#debug "Done\n"
2910
2911#end
2912
2913// =======================================================================================
2914//  MechSim_Generate_Patch() macro
2915//
2916//  topology generation macro building a rectangular patch of masses connected and with
2917//  optional faces.
2918//
2919//  Parameters:
2920//      Velocity    - common velocity of all masses
2921//      Radius      - radius of the masses
2922//      Density     - density of the masses
2923//      Stiffness   - stiffness of the connections
2924//      Damping     - damping of the connections
2925//      Faces       - Boolean value controlling whether faces are generated for the
2926//                    surface.
2927//      Rect_Scale  - 2D Grid distance vector, defining the size of an elemetary
2928//                    rectangle in the grid.
2929//      Grid_Size   - 2D Vector with number of masses in x and y direction
2930//      Transf      - Transform applied to the mass positions
2931//      fn_Fixed    - user defined function controlling which masses are fixed.
2932//									  x and y are evaluated in [0..1] range. For function values > 0 the masses are fixed.
2933//      fn_Attach   - user defined function controlling which masses are fixed.
2934//                    x and y are evaluated in [0..1] range. The function value determines the attachment index.
2935//      fn_Force     - user defined function controlling custom forces.
2936//                    x and y are evaluated in [0..1] range. The function value determines the custom force index.
2937//      Connect_Arr - Array containing weights for connection stiffness and damping
2938//
2939// =======================================================================================
2940#macro MechSim_Generate_Patch(Velocity, Radius, Density, Stiffness, Damping, Faces, Rect_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr)
2941
2942	#local VE_Elements=array[1]
2943	#local VE_Accuracy=0;
2944
2945  MechSim_Generate_Patch_X(
2946		Velocity, Radius, Density, Stiffness, Damping, VE_Elements, VE_Accuracy, Faces,
2947		Rect_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr
2948	)
2949
2950#end
2951
2952// =======================================================================================
2953//  MechSim_Generate_Patch_VE() macro
2954//
2955//  variant of MechSim_Generate_Patch() generating viscoelastic connections
2956//
2957//  Parameters:
2958//      Velocity    - common velocity of all masses
2959//      Radius      - radius of the masses
2960//      Density     - density of the masses
2961//      Stiffness   - stiffness of the connections
2962//      VE_Elements - array with the parameters for viscoelastic connections
2963//      VE_Accuracy - accuracy value for viscoelastic connection
2964//      Faces       - Boolean value controlling whether faces are generated for the
2965//                    surface.
2966//      Rect_Scale  - 2D Grid distance vector, defining the size of an elemetary
2967//                    rectangle in the grid.
2968//      Grid_Size   - 2D Vector with number of masses in x and y direction
2969//      Transf      - Transform applied to the mass positions
2970//      fn_Fixed    - user defined function controlling which masses are fixed.
2971//									  x and y are evaluated in [0..1] range. For function values > 0 the masses are fixed.
2972//      fn_Attach   - user defined function controlling which masses are fixed.
2973//                    x and y are evaluated in [0..1] range. The function value determines the attachment index.
2974//      fn_Force     - user defined function controlling custom forces.
2975//                    x and y are evaluated in [0..1] range. The function value determines the custom force index.
2976//      Connect_Arr - Array containing weights for connection stiffness and damping
2977//
2978// =======================================================================================
2979#macro MechSim_Generate_Patch_VE(Velocity, Radius, Density, Stiffness, VE_Elements, VE_Accuracy, Faces, Rect_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr)
2980
2981  MechSim_Generate_Patch_X(
2982		Velocity, Radius, Density, Stiffness, 0, VE_Elements, VE_Accuracy, Faces,
2983		Rect_Scale, Grid_Size, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr
2984	)
2985
2986#end
2987
2988// =======================================================================================
2989//  MechSim_Generate_Patch_Std() macro
2990//
2991//  topology generation macro building a rectangular patch of masses connected and with
2992//  optional faces. No nodes fixed and same stiffness and damping for all connections.
2993//
2994//  Parameters:
2995//      Velocity    - common velocity of all masses
2996//      Radius      - radius of the masses
2997//      Density     - density of the masses
2998//      Stiffness   - stiffness of the connections
2999//      Damping     - damping of the connections
3000//      Faces       - Boolean value controlling whether faces are generated for the
3001//                    surface.
3002//      Rect_Scale  - 2D Grid distance vector, defining the size of an elemetary
3003//                    rectangle in the grid.
3004//      Grid_Size   - 2D Vector with number of masses in x and y direction
3005//      Transf      - Transform applied to the mass positions
3006//      Connect     - Which connections to generate
3007//
3008// =======================================================================================
3009#macro MechSim_Generate_Patch_Std(Velocity, Radius, Density, Stiffness, Damping, Faces, Rect_Scale, Grid_Size, Transf, Connect)
3010
3011	#local __MSIM_fn_Fixed=function(x, y, z) { -1 }
3012	#local __MSIM_fn_Attach=function(x, y, z) { -1 }
3013	#local __MSIM_fn_Force=function(x, y, z) { -1 }
3014	#local Connect_Arr=array[Connect]
3015
3016	#local Cnt=0;
3017	#while (Cnt<Connect)
3018		#local Connect_Arr[Cnt]=1;
3019		#local Cnt=Cnt+1;
3020	#end
3021
3022	MechSim_Generate_Patch(
3023		Velocity, Radius, Density, Stiffness, Damping, Faces, Rect_Scale, Grid_Size,
3024		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr
3025	)
3026
3027#end
3028
3029// #######################################################################################
3030//   Line topology generation macros
3031// #######################################################################################
3032
3033// =======================================================================================
3034//  MechSim_Generate_Line() macro
3035//
3036//  topology generation macro building a straight line of masses connected.
3037//
3038//  Parameters:
3039//      Velocity    - common velocity of all masses
3040//      Radius      - radius of the masses
3041//      Density     - density of the masses
3042//      Stiffness   - stiffness of the connections
3043//      Damping     - damping of the connections
3044//      Spacing     - Distance between the masses
3045//      Count       - Number of masses
3046//      Direction   - Direction vector of the line
3047//      Transf      - Transform applied to the mass positions
3048//      fn_Fixed    - function controlling which nodes are fixed
3049//									  x is evaluated in [0..1] range. For function values > 0 the masses are fixed.
3050//      fn_Attach   - user defined function controlling which masses are fixed.
3051//                    x is evaluated in [0..1] range. The function value determines the attachment index.
3052//      fn_Force    - user defined function controlling which masses are fixed.
3053//                    x is evaluated in [0..1] range. The function value determines the attachment index.
3054//      Connect_Arr - Array containing weights for connection stiffness and damping
3055//
3056// =======================================================================================
3057#macro MechSim_Generate_Line(Velocity, Radius, Density, Stiffness, Damping, Spacing, Count, Direction, Transf, fn_Fixed, fn_Attach, fn_Force, Connect_Arr)
3058
3059	#debug "Generating Line..."
3060
3061	#local Vel=Velocity+<0,0,0>;
3062	#local Dir=vnormalize(Direction);
3063
3064	#local StIdx=mechsim:mass_count;
3065	#local Con_Cnt=dimension_size(Connect_Arr, 1);
3066
3067	#if (Con_Cnt>0)
3068
3069		#local Cnt=0;
3070
3071		#while (Cnt<Count)
3072
3073			mass {
3074				vtransform(Dir*Cnt*Spacing, Transf), Velocity, Radius density Density
3075
3076				#if ( fn_Fixed(Cnt/(Count-1), 0, 0)>0 )
3077					fixed on
3078				#else
3079					#local Attach=fn_Attach(Cnt/(Count-1), 0, 0);
3080					#if ( Attach>-0.1 )
3081						attach Attach
3082					#end
3083					#local Force=fn_Force(Cnt/(Count-1), 0, 0);
3084					#if ( Force>-0.1 )
3085						force Force
3086					#end
3087				#end
3088			}
3089
3090			#local Cnt=Cnt+1;
3091		#end
3092
3093
3094		#if (Con_Cnt>0)
3095
3096			#local Cnt=0;
3097
3098			#while (Cnt<Count-1)
3099
3100				#local BCnt=0;
3101				#while ((BCnt<Con_Cnt) & ((Cnt+BCnt)<Count-1))
3102
3103					connection {
3104						StIdx+Cnt,
3105						StIdx+Cnt+BCnt+1
3106						stiffness Stiffness*Connect_Arr[BCnt]
3107						damping Damping*Connect_Arr[BCnt]
3108						length Spacing*(BCnt+1)
3109					}
3110
3111					#local BCnt=BCnt+1;
3112				#end
3113
3114				#local Cnt=Cnt+1;
3115			#end
3116
3117		#end
3118
3119	#end
3120
3121	#debug "Done\n"
3122
3123#end
3124
3125// =======================================================================================
3126//  MechSim_Generate_Line_Std() macro
3127//
3128//  topology generation macro building a straight line of masses connected.
3129//  Only simple connections and not fixed
3130//
3131//  Parameters:
3132//      Velocity    - common velocity of all masses
3133//      Radius      - radius of the masses
3134//      Density     - density of the masses
3135//      Stiffness   - stiffness of the connections
3136//      Damping     - damping of the connections
3137//      Spacing     - Distance between the masses
3138//      Count       - Number of masses
3139//      Direction   - Direction vector of the line
3140//      Transf      - Transform applied to the mass positions
3141//
3142// =======================================================================================
3143#macro MechSim_Generate_Line_Std(Velocity, Radius, Density, Stiffness, Damping, Spacing, Count, Direction, Transf)
3144
3145	#local __MSIM_fn_Fixed=function(x, y, z) { -1 }
3146	#local __MSIM_fn_Attach=function(x, y, z) { -1 }
3147	#local __MSIM_fn_Force=function(x, y, z) { -1 }
3148	#local Connect_Arr=array[1]
3149	#local Connect_Arr[0]=1;
3150
3151	MechSim_Generate_Line(
3152		Velocity, Radius, Density, Stiffness, Damping, Spacing, Count, Direction,
3153		Transf, __MSIM_fn_Fixed, __MSIM_fn_Attach, __MSIM_fn_Force, Connect_Arr)
3154
3155#end
3156
3157// #######################################################################################
3158//   Ball topology generation macros
3159// #######################################################################################
3160
3161// --- Icosahedron data ---
3162
3163#declare Icosahedron_Vtx = array[12]
3164
3165#local ZPos=1-4/(5+sqrt(5));
3166#local Rad=sqrt(1-ZPos*ZPos);
3167#local Cnt=1;
3168#while (Cnt<6)
3169	#declare Icosahedron_Vtx[  Cnt]=<Rad*cos(Cnt*2*pi/5),Rad*sin(Cnt*2*pi/5),-ZPos>;
3170	#declare Icosahedron_Vtx[5+Cnt]=<Rad*cos((Cnt-7.5)*2*pi/5),Rad*sin((Cnt-7.5)*2*pi/5),ZPos>;
3171	#declare Cnt=Cnt+1;
3172#end
3173#declare Icosahedron_Vtx[0]=<0,0,-1>;
3174#declare Icosahedron_Vtx[11]=<0,0,1>;
3175
3176#declare Icosahedron_Face = array[20]
3177
3178#declare Icosahedron_Face[ 0]=< 0, 1, 2>;
3179#declare Icosahedron_Face[ 1]=< 0, 2, 3>;
3180#declare Icosahedron_Face[ 2]=< 0, 3, 4>;
3181#declare Icosahedron_Face[ 3]=< 0, 4, 5>;
3182#declare Icosahedron_Face[ 4]=< 0, 5, 1>;
3183#declare Icosahedron_Face[ 5]=< 1, 2, 9>;
3184#declare Icosahedron_Face[ 6]=< 2, 3,10>;
3185#declare Icosahedron_Face[ 7]=< 3, 4, 6>;
3186#declare Icosahedron_Face[ 8]=< 4, 5, 7>;
3187#declare Icosahedron_Face[ 9]=< 5, 1, 8>;
3188#declare Icosahedron_Face[10]=< 1, 8, 9>;
3189#declare Icosahedron_Face[11]=< 9,10, 2>;
3190#declare Icosahedron_Face[12]=<10, 6, 3>;
3191#declare Icosahedron_Face[13]=< 6, 7, 4>;
3192#declare Icosahedron_Face[14]=< 7, 8, 5>;
3193#declare Icosahedron_Face[15]=<11, 6, 7>;
3194#declare Icosahedron_Face[16]=<11, 7, 8>;
3195#declare Icosahedron_Face[17]=<11, 8, 9>;
3196#declare Icosahedron_Face[18]=<11, 9,10>;
3197#declare Icosahedron_Face[19]=<11,10, 6>;
3198
3199// --- Builds a triangle mesh from Vertex and Face arrays ---
3200
3201#macro MechSim_Ico_Build_Mesh(Arr_V, Arr_F)
3202
3203	#local Cnt_F=dimension_size(Arr_F, 1);
3204
3205	#local Cnt=0;
3206	#while (Cnt<Cnt_F)
3207
3208		triangle { Arr_V[Arr_F[Cnt].x], Arr_V[Arr_F[Cnt].y], Arr_V[Arr_F[Cnt].z] }
3209
3210		#local Cnt=Cnt+1;
3211	#end
3212
3213#end
3214
3215// --- Builds a mechsim topology from Vertex and Face arrays ---
3216
3217#macro MechSim_Ico_Build_Grid(Cnt_E, Arr_V, Arr_F, Velocity, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, BRadius, Transf)
3218
3219	#local StIdx=mechsim:mass_count;
3220	#local Cnt_V=dimension_size(Arr_V, 1);
3221	#local Cnt_F=dimension_size(Arr_F, 1);
3222
3223	#local Arr_E=array[Cnt_E]
3224	#local Is=array[3];
3225
3226	#local FCnt=0;
3227	#local EnCnt=0;
3228
3229	#while (FCnt<Cnt_F)
3230
3231		#local Cnt=0;
3232		#local Is[0]=false;
3233		#local Is[1]=false;
3234		#local Is[2]=false;
3235
3236		#while (Cnt<EnCnt)
3237
3238				#if (((Arr_E[Cnt].x=Arr_F[FCnt].x)&(Arr_E[Cnt].y=Arr_F[FCnt].y))|
3239					   ((Arr_E[Cnt].y=Arr_F[FCnt].x)&(Arr_E[Cnt].x=Arr_F[FCnt].y)))
3240					#local Is[0]=true;
3241				#end
3242				#if (((Arr_E[Cnt].x=Arr_F[FCnt].y)&(Arr_E[Cnt].y=Arr_F[FCnt].z))|
3243					   ((Arr_E[Cnt].y=Arr_F[FCnt].y)&(Arr_E[Cnt].x=Arr_F[FCnt].z)))
3244					#local Is[1]=true;
3245				#end
3246				#if (((Arr_E[Cnt].x=Arr_F[FCnt].z)&(Arr_E[Cnt].y=Arr_F[FCnt].x))|
3247					   ((Arr_E[Cnt].y=Arr_F[FCnt].z)&(Arr_E[Cnt].x=Arr_F[FCnt].x)))
3248					#local Is[2]=true;
3249				#end
3250
3251			#local Cnt=Cnt+1;
3252		#end
3253
3254		#if (Is[0]=false)
3255			#local Arr_E[EnCnt]=<Arr_F[FCnt].x, Arr_F[FCnt].y>;
3256			#local EnCnt=EnCnt+1;
3257		#end
3258		#if (Is[1]=false)
3259			#local Arr_E[EnCnt]=<Arr_F[FCnt].y, Arr_F[FCnt].z>;
3260			#local EnCnt=EnCnt+1;
3261		#end
3262		#if (Is[2]=false)
3263			#local Arr_E[EnCnt]=<Arr_F[FCnt].z, Arr_F[FCnt].x>;
3264			#local EnCnt=EnCnt+1;
3265		#end
3266
3267		#local FCnt=FCnt+1;
3268	#end
3269
3270	// center mass
3271	#local Center_Pos=vtransform(<0,0,0>, Transf);
3272	mass {
3273		Center_Pos, Velocity, Radius density Density2
3274	}
3275
3276	#local Cnt=0;
3277	#while (Cnt<Cnt_V)
3278
3279		#local MPosition=vtransform(Arr_V[Cnt]*BRadius, Transf);
3280
3281		mass {
3282			MPosition, Velocity, Radius density Density
3283		}
3284
3285		connection {
3286			StIdx, StIdx+Cnt+1 stiffness Stiffness2 damping Damping2
3287			length vlength(MPosition-Center_Pos)
3288		}
3289
3290		#local Cnt=Cnt+1;
3291	#end
3292
3293	#local Cnt=0;
3294	#while (Cnt<EnCnt)
3295
3296		#local MPosition1=vtransform(Arr_V[Arr_E[Cnt].x]*BRadius, Transf);
3297		#local MPosition2=vtransform(Arr_V[Arr_E[Cnt].y]*BRadius, Transf);
3298
3299		connection {
3300			StIdx+Arr_E[Cnt].x+1, StIdx+Arr_E[Cnt].y+1 stiffness Stiffness damping Damping
3301			length vlength(MPosition1-MPosition2)
3302		}
3303
3304		#local Cnt=Cnt+1;
3305	#end
3306
3307	#if (Faces)
3308		#local Cnt=0;
3309		#while (Cnt<Cnt_F)
3310
3311			face {
3312				StIdx+Arr_F[Cnt].x+1,
3313				StIdx+Arr_F[Cnt].y+1,
3314				StIdx+Arr_F[Cnt].z+1
3315			}
3316
3317			#local Cnt=Cnt+1;
3318		#end
3319	#end
3320
3321#end
3322
3323//  Pnt6 indices:
3324//
3325//      0
3326//     / \
3327//    5---3
3328//   / \ / \
3329//  2---4---1
3330
3331#macro MechSim_Subdivide_Ico_Rec(Depth, Cnt_V, Cnt_F, Cnt_E, Arr_V, Arr_F, Velocity, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, BRadius, Transf)
3332
3333	#if (Depth>0)
3334
3335		#local Cnt_Vn=Cnt_V+Cnt_E;
3336		#local Cnt_Fn=4*Cnt_F;
3337		#local Cnt_En=2*Cnt_E + 3*Cnt_F;
3338
3339		#local Arr_Vn=array[Cnt_Vn]
3340		#local Arr_Fn=array[Cnt_Fn]
3341		#local Pnt6=array[6]
3342
3343		#local FCnt=0;
3344		#local FnCnt=0;
3345		#local VnCnt=0;
3346
3347		#while (FCnt<Cnt_F)
3348
3349			#local Cnt=0;
3350			#while (Cnt<6)
3351				#local Pnt6[Cnt]=-1;
3352				#local Cnt=Cnt+1;
3353			#end
3354
3355			#local Mid1 = vnormalize(Arr_V[Arr_F[FCnt].x]+Arr_V[Arr_F[FCnt].y]);
3356			#local Mid2 = vnormalize(Arr_V[Arr_F[FCnt].y]+Arr_V[Arr_F[FCnt].z]);
3357			#local Mid3 = vnormalize(Arr_V[Arr_F[FCnt].z]+Arr_V[Arr_F[FCnt].x]);
3358
3359			#local Cnt=0;
3360			#while (Cnt<VnCnt)
3361
3362				#if (vlength(Arr_Vn[Cnt]-Arr_V[Arr_F[FCnt].x])<1e-6)
3363					#local Pnt6[0]=Cnt;
3364				#end
3365				#if (vlength(Arr_Vn[Cnt]-Arr_V[Arr_F[FCnt].y])<1e-6)
3366					#local Pnt6[1]=Cnt;
3367				#end
3368				#if (vlength(Arr_Vn[Cnt]-Arr_V[Arr_F[FCnt].z])<1e-6)
3369					#local Pnt6[2]=Cnt;
3370				#end
3371				#if (vlength(Arr_Vn[Cnt]-Mid1)<1e-6)
3372					#local Pnt6[3]=Cnt;
3373				#end
3374				#if (vlength(Arr_Vn[Cnt]-Mid2)<1e-6)
3375					#local Pnt6[4]=Cnt;
3376				#end
3377				#if (vlength(Arr_Vn[Cnt]-Mid3)<1e-6)
3378					#local Pnt6[5]=Cnt;
3379				#end
3380
3381				#local Cnt=Cnt+1;
3382			#end
3383
3384			#if (Pnt6[0]<0)
3385				#local Arr_Vn[VnCnt]=Arr_V[Arr_F[FCnt].x];
3386				#local Pnt6[0]=VnCnt;
3387				#local VnCnt=VnCnt+1;
3388			#end
3389			#if (Pnt6[1]<0)
3390				#local Arr_Vn[VnCnt]=Arr_V[Arr_F[FCnt].y];
3391				#local Pnt6[1]=VnCnt;
3392				#local VnCnt=VnCnt+1;
3393			#end
3394			#if (Pnt6[2]<0)
3395				#local Arr_Vn[VnCnt]=Arr_V[Arr_F[FCnt].z];
3396				#local Pnt6[2]=VnCnt;
3397				#local VnCnt=VnCnt+1;
3398			#end
3399			#if (Pnt6[3]<0)
3400				#local Arr_Vn[VnCnt]=Mid1;
3401				#local Pnt6[3]=VnCnt;
3402				#local VnCnt=VnCnt+1;
3403			#end
3404			#if (Pnt6[4]<0)
3405				#local Arr_Vn[VnCnt]=Mid2;
3406				#local Pnt6[4]=VnCnt;
3407				#local VnCnt=VnCnt+1;
3408			#end
3409			#if (Pnt6[5]<0)
3410				#local Arr_Vn[VnCnt]=Mid3;
3411				#local Pnt6[5]=VnCnt;
3412				#local VnCnt=VnCnt+1;
3413			#end
3414
3415			#local Arr_Fn[FnCnt]=<Pnt6[0], Pnt6[3], Pnt6[5]>;
3416			#local FnCnt=FnCnt+1;
3417			#local Arr_Fn[FnCnt]=<Pnt6[1], Pnt6[4], Pnt6[3]>;
3418			#local FnCnt=FnCnt+1;
3419			#local Arr_Fn[FnCnt]=<Pnt6[2], Pnt6[5], Pnt6[4]>;
3420			#local FnCnt=FnCnt+1;
3421			#local Arr_Fn[FnCnt]=<Pnt6[3], Pnt6[4], Pnt6[5]>;
3422			#local FnCnt=FnCnt+1;
3423
3424			#local FCnt=FCnt+1;
3425		#end
3426
3427		#if (Depth>1)
3428
3429			MechSim_Subdivide_Ico_Rec(Depth-1, Cnt_Vn, Cnt_Fn, Cnt_En, Arr_Vn, Arr_Fn, Velocity, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, BRadius, Transf)
3430
3431		#else
3432
3433			MechSim_Ico_Build_Grid(Cnt_En, Arr_Vn, Arr_Fn, Velocity, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, BRadius, Transf)
3434
3435		#end
3436
3437	#end
3438
3439#end
3440
3441#macro MechSim_Subdivide_Ico(Depth, Velocity, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, Division, BRadius, Transf)
3442
3443  #local Cnt_V=12;
3444  #local Cnt_F=20;
3445  #local Cnt_E=30;
3446
3447  #local Arr_V=Icosahedron_Vtx;
3448  #local Arr_F=Icosahedron_Face;
3449
3450  MechSim_Subdivide_Ico_Rec(Division, Cnt_V, Cnt_F, Cnt_E, Arr_V, Arr_F, Velocity, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, BRadius, Transf)
3451
3452#end
3453
3454// =======================================================================================
3455//  MechSim_Generate_Sphere() macro
3456//
3457//  topology generation macro building a sphere.
3458//  Only simple connections and not fixed
3459//
3460//  Parameters:
3461//      Velocity    - common velocity of all masses
3462//      Radius      - radius of the masses
3463//      Density     - density of the surface masses
3464//      Stiffness   - stiffness of the surface connections
3465//      Damping     - damping of the surface connections
3466//      Density2    - density of the center mass
3467//      Stiffness2  - stiffness of the center connections
3468//      Damping2    - damping of the center connections
3469//      Division    - Icosahedron subdivision depth
3470//      BRadius     - Radius of the ball
3471//      Transf      - Transform applied to the mass positions
3472//
3473// =======================================================================================
3474#macro MechSim_Generate_Sphere(Velocity, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, Division, BRadius, Transf)
3475
3476	#debug "Generating Sphere...\n"
3477
3478	#local Vel=Velocity+<0,0,0>;
3479
3480	 MechSim_Subdivide_Ico(Division, Vel, Radius, Density, Stiffness, Damping, Density2, Stiffness2, Damping2, Faces, Division, BRadius, Transf)
3481
3482	#debug "Done\n"
3483
3484#end
3485
3486
3487#version MECHSIM_Inc_Temp;
3488#end
3489