Break_mesh_by_cracks.py

Break_mesh_by_cracks.py#

:Break_mesh_by_cracks.py
Break_mesh_by_cracks.py

Break the current volume with realistic cracks

1import random
2import coat
3from coat import vec3
4from coat import Mesh
5
6# we take the current volume
7v = coat.Scene.current().Volume()
8m = Mesh()
9# we create the mesh from the volume
10m.fromVolume(v)
11global_center = m.getCenterMass()
12# initial mesh size
13initial_mesh_scale = m.getBounds().GetDiagonal() / 2.0
14# the scale of the Perlin noise
15noise_scale = initial_mesh_scale / 3.0
16
17# the class to edit and store the parameters
18class Cuts:
19 def __init__(self):
20 self.Cuts = 16
21 self.ExplodingDegree = 1.0
22 self.RandomShuffle = 1.0
23 self.RandomRotation = 4.0
24 self.NoiseDegree = 100.0
25 self.NoiseScale = 100.0
26 def ui(self):
27 return [
28 'Cuts,[1,100]',
29 'ExplodingDegree,[0,100]',
30 'RandomShuffle,[0,100]',
31 'RandomRotation,[0,90]',
32 'NoiseDegree,[0,500]',
33 'NoiseScale,[0,500]'
34 ]
35
36# if mesh is empty, we warn
37if m.facesCount() == 0 :
38 coat.dialog().ok().text("Please select any non-trivial surface-based volume.").show()
39else:
40 param = Cuts()
41 # restore the parameters from the file
42 coat.io.fromJsonFile(param, "data/Temp/Cuts.json")
43 # the dialog to enter the parameters
44 if coat.dialog().ok().cancel().params(param).text("Please enter the amount of cuts, exploding degree, noise parameters:").show() == 1 :
45 # save the parameters to the file
46 coat.io.toJson(param, "data/Temp/Cuts.json")
47 # the scale of the Perlin noise
48 noise_scale *= param.NoiseScale / 100.0
49 #the meshes list, initially we put there the original mesh
50 meshes = [m]
51 # function to find the biggest piece approximately and randomly, we estimate by the mesh square
52 def biggest_mesh() :
53 num = len(meshes)
54 # take the random mesh as the biggest
55 mbest=index = random.randint(0, num-1)
56 # calculate the square of the mesh
57 biggest = meshes[mbest].getSquare()
58 # sevearal times we take the random mesh and compare the square
59 for i in range(3):
60 index = random.randint(0, num-1)
61 mesh = meshes[index]
62 square = mesh.getSquare()
63 if square > biggest :
64 biggest = square
65 mbest = index
66 # we remove the biggest mesh from the list and return it
67 return meshes.pop(mbest)
68
69 # in cycle we find the approximately biggest piece and cut it in the middle by the random screwed plane
70 for i in range(param.Cuts) :
71 coat.io.progressBar(i, param.Cuts, "Cutting the mesh...")
72 m0 = biggest_mesh()
73 # we relax the mesh just a little to make booleans stable
74 m0.relax(0.15,False,180)
75 m1 = m0.MakeCopy()
76 bestN = vec3.RandNormal()
77 # we find the best direction to cut the mesh
78 best_len = m0.getLengthAlongDirection(bestN)
79 for j in range(20) :
80 dir = vec3.RandNormal()
81 axis_length = m0.getLengthAlongDirection(dir)
82 # if the length is bigger than the previous one, we take it as the best
83 if(axis_length > best_len) :
84 best_len = axis_length
85 bestN = coat.vec3(dir)
86
87 # we cut the mesh by the plane at it's center mass
88 center = m0.getCenterMass()
89 N0 = m0.vertsCount()
90 degree = noise_scale*0.1*param.NoiseDegree/100.0
91 m0.cutByDistortedPlane(center, bestN, degree, noise_scale, 0)
92 N1 = m0.vertsCount()
93 # if vertices count changes, the mesh was cut successfully
94 if N1 != N0 :
95 m1.cutByDistortedPlane(center, -bestN, -degree, noise_scale, 0)
96 meshes0 = m0.splitDisconnectedParts()
97 meshes1 = m1.splitDisconnectedParts()
98 meshes.extend(meshes0)
99 meshes.extend(meshes1)
100 else :
101 # if the mesh was not cut, we return it back to the list
102 meshes.append(m0)
103
104 # clear the initial object
105 v.clear()
106 # merge meshes one-by-one
107 for ms in meshes :
108 # we want to push the mesh out of the center
109 mesh_center = ms.getCenterMass()
110 shift = vec3(mesh_center)
111 shift -= global_center
112 shift *= param.ExplodingDegree / 100.0
113 shift += vec3.RandNormal() * param.RandomShuffle * initial_mesh_scale / 100.0
114 # transform the mesh (translate), you may add random rotation to improve the effect
115 ms.transform(coat.mat4.Translation(shift))
116 ms.transform(coat.mat4.RotationAt(mesh_center, vec3.RandNormal(), random.uniform(-param.RandomRotation, param.RandomRotation)))
117 v.mergeMesh(ms)
:Break_mesh_by_cracks.py
  1     import random
  2     import coat
  3     from coat import vec3
  4     from coat import Mesh
  5
  6     # we take the current volume
  7     v = coat.Scene.current().Volume()
  8     m = Mesh()
  9     # we create the mesh from the volume
 10     m.fromVolume(v)
 11     global_center = m.getCenterMass()
 12     # initial mesh size
 13     initial_mesh_scale = m.getBounds().GetDiagonal() / 2.0
 14     # the scale of the Perlin noise
 15     noise_scale = initial_mesh_scale / 3.0
 16
 17     # the class to edit and store the parameters
 18     class Cuts:
 19             def __init__(self):
 20                     self.Cuts = 16
 21                     self.ExplodingDegree = 1.0
 22                     self.RandomShuffle = 1.0
 23                     self.RandomRotation = 4.0
 24                     self.NoiseDegree = 100.0
 25                     self.NoiseScale = 100.0
 26
 27             def ui(self):
 28                     return [
 29                             'Cuts,[1,100]',
 30                             'ExplodingDegree,[0,100]',
 31                             'RandomShuffle,[0,100]',
 32                             'RandomRotation,[0,90]',
 33                             'NoiseDegree,[0,500]',
 34                             'NoiseScale,[0,500]'
 35                     ]
 36
 37     # if mesh is empty, we warn
 38     if m.facesCount() == 0 :
 39             coat.dialog().ok().text("Please select any non-trivial surface-based volume.").show()
 40     else:
 41             param = Cuts()
 42             # restore the parameters from the file
 43             coat.io.fromJsonFile(param, "data/Temp/Cuts.json")
 44             # the dialog to enter the parameters
 45             if coat.dialog().ok().cancel().params(param).text("Please enter the amount of cuts, exploding degree, noise parameters:").show() == 1 :
 46                     # save the parameters to the file
 47                     coat.io.toJson(param, "data/Temp/Cuts.json")
 48                     # the scale of the Perlin noise
 49                     noise_scale *= param.NoiseScale / 100.0
 50                     #the meshes list, initially we put there the original mesh
 51                     meshes = [m]
 52                     # function to find the biggest piece approximately and randomly, we estimate by the mesh square
 53                     def biggest_mesh() :
 54                             num = len(meshes)
 55                             # take the random mesh as the biggest
 56                             mbest=index = random.randint(0, num-1)
 57                             # calculate the square of the mesh
 58                             biggest = meshes[mbest].getSquare()
 59                             # sevearal times we take the random mesh and compare the square
 60                             for i in range(3):
 61                                     index = random.randint(0, num-1)
 62                                     mesh = meshes[index]
 63                                     square = mesh.getSquare()
 64                                     if square > biggest :
 65                                             biggest = square
 66                                             mbest = index
 67                             # we remove the biggest mesh from the list and return it
 68                             return meshes.pop(mbest)
 69
 70                     # in cycle we find the approximately biggest piece and cut it in the middle by the random screwed plane
 71                     for i in range(param.Cuts) :
 72                             coat.io.progressBar(i, param.Cuts, "Cutting the mesh...")
 73                             m0 = biggest_mesh()
 74                             # we relax the mesh just a little to make booleans stable
 75                             m0.relax(0.15,False,180)
 76                             m1 = m0.MakeCopy()
 77                             bestN = vec3.RandNormal()
 78                             # we find the best direction to cut the mesh
 79                             best_len = m0.getLengthAlongDirection(bestN)
 80                             for j in range(20) :
 81                                     dir = vec3.RandNormal()
 82                                     axis_length = m0.getLengthAlongDirection(dir)
 83                                     # if the length is bigger than the previous one, we take it as the best
 84                                     if(axis_length > best_len) :
 85                                             best_len = axis_length
 86                                             bestN = coat.vec3(dir)
 87
 88                             # we cut the mesh by the plane at it's center mass
 89                             center = m0.getCenterMass()
 90                             N0 = m0.vertsCount()
 91                             degree = noise_scale*0.1*param.NoiseDegree/100.0
 92                             m0.cutByDistortedPlane(center, bestN, degree, noise_scale, 0)
 93                             N1 = m0.vertsCount()
 94                             # if vertices count changes, the mesh was cut successfully
 95                             if N1 != N0 :
 96                                     m1.cutByDistortedPlane(center, -bestN, -degree, noise_scale, 0)
 97                                     meshes0 = m0.splitDisconnectedParts()
 98                                     meshes1 = m1.splitDisconnectedParts()
 99                                     meshes.extend(meshes0)
100                                     meshes.extend(meshes1)
101                             else :
102                                     # if the mesh was not cut, we return it back to the list
103                                     meshes.append(m0)
104
105                     # clear the initial object
106                     v.clear()
107                     # merge meshes one-by-one
108                     for ms in meshes :
109                             # we want to push the mesh out of the center
110                             mesh_center = ms.getCenterMass()
111                             shift = vec3(mesh_center)
112                             shift -= global_center
113                             shift *= param.ExplodingDegree / 100.0
114                             shift += vec3.RandNormal() * param.RandomShuffle * initial_mesh_scale / 100.0
115                             # transform the mesh (translate), you may add random rotation to improve the effect
116                             ms.transform(coat.mat4.Translation(shift))
117                             ms.transform(coat.mat4.RotationAt(mesh_center, vec3.RandNormal(), random.uniform(-param.RandomRotation, param.RandomRotation)))
118                             v.mergeMesh(ms)