4 from . import mathematics
9 class LoftedSplineSurface
:
10 def __init__(self
, activeSpline
, otherSpline
, bMesh
, vert0Index
, resolution
):
11 self
.splineA
= activeSpline
12 self
.splineO
= otherSpline
15 self
.vert0Index
= vert0Index
16 self
.resolution
= resolution
19 def Apply(self
, worldMatrixA
, worldMatrixO
):
20 #deltaPar = 1.0 / float(self.resolution - 1)
23 pointA
= worldMatrixA
@ self
.splineA
.CalcPoint(par
)
24 pointO
= worldMatrixO
@ self
.splineO
.CalcPoint(par
)
25 self
.bMesh
.verts
[self
.vert0Index
].co
= pointA
26 self
.bMesh
.verts
[self
.vert0Index
+ 1].co
= pointO
28 fltResm1
= float(self
.resolution
- 1)
29 for i
in range(1, self
.resolution
):
30 par
= float(i
) / fltResm1
32 pointA
= worldMatrixA
@ self
.splineA
.CalcPoint(par
)
33 pointO
= worldMatrixO
@ self
.splineO
.CalcPoint(par
)
34 self
.bMesh
.verts
[self
.vert0Index
+ 2 * i
].co
= pointA
35 self
.bMesh
.verts
[self
.vert0Index
+ 2 * i
+ 1].co
= pointO
39 currIndexA
= self
.vert0Index
40 currIndexO
= self
.vert0Index
+ 1
42 bmVerts
= self
.bMesh
.verts
43 bmVerts
.ensure_lookup_table()
45 for i
in range(1, self
.resolution
):
46 nextIndexA
= self
.vert0Index
+ 2 * i
47 nextIndexO
= nextIndexA
+ 1
49 self
.bMesh
.faces
.new([bmVerts
[currIndexA
], bmVerts
[currIndexO
], bmVerts
[nextIndexO
], bmVerts
[nextIndexA
]])
51 currIndexA
= nextIndexA
52 currIndexO
= nextIndexO
58 selObjects
= bpy
.context
.selected_objects
59 if len(selObjects
) != 2: raise Exception("len(selObjects) != 2") # shouldn't be possible
61 blenderActiveCurve
= bpy
.context
.active_object
62 blenderOtherCurve
= selObjects
[0]
63 if blenderActiveCurve
== blenderOtherCurve
: blenderOtherCurve
= selObjects
[1]
65 aCurve
= curves
.Curve(blenderActiveCurve
)
66 oCurve
= curves
.Curve(blenderOtherCurve
)
68 name
= "TODO: autoname"
70 return LoftedSurface(aCurve
, oCurve
, name
)
73 def __init__(self
, activeCurve
, otherCurve
, name
= "LoftedSurface"):
74 self
.curveA
= activeCurve
75 self
.curveO
= otherCurve
78 self
.nrSplines
= self
.curveA
.nrSplines
79 if self
.curveO
.nrSplines
< self
.nrSplines
: self
.nrSplines
= self
.curveO
.nrSplines
81 self
.bMesh
= bmesh
.new()
83 self
.splineSurfaces
= self
.SetupSplineSurfaces()
88 def SetupSplineSurfaces(self
):
92 for i
in range(self
.nrSplines
):
93 splineA
= self
.curveA
.splines
[i
]
94 splineO
= self
.curveO
.splines
[i
]
96 res
= splineA
.resolution
97 if splineO
.resolution
< res
: res
= splineO
.resolution
99 for iv
in range(2 * res
): self
.bMesh
.verts
.new()
101 splSurf
= LoftedSplineSurface(splineA
, splineO
, self
.bMesh
, currV0Index
, res
)
103 rvSplineSurfaces
.append(splSurf
)
105 currV0Index
+= 2 * res
107 return rvSplineSurfaces
111 for splineSurface
in self
.splineSurfaces
: splineSurface
.Apply(self
.curveA
.worldMatrix
, self
.curveO
.worldMatrix
)
114 def AddToScene(self
):
115 mesh
= bpy
.data
.meshes
.new("Mesh" + self
.name
)
117 self
.bMesh
.to_mesh(mesh
)
120 meshObject
= bpy
.data
.objects
.new(self
.name
, mesh
)
122 bpy
.context
.collection
.objects
.link(meshObject
)
126 # active spline is swept over other spline (rail)
127 class SweptSplineSurface
:
128 def __init__(self
, activeSpline
, otherSpline
, bMesh
, vert0Index
, resolutionA
, resolutionO
):
129 self
.splineA
= activeSpline
130 self
.splineO
= otherSpline
133 self
.vert0Index
= vert0Index
134 self
.resolutionA
= resolutionA
135 self
.resolutionO
= resolutionO
138 def Apply(self
, worldMatrixA
, worldMatrixO
):
140 fltResAm1
= float(self
.resolutionA
- 1)
141 for i
in range(self
.resolutionA
):
142 par
= float(i
) / fltResAm1
143 pointA
= self
.splineA
.CalcPoint(par
)
144 localPointsA
.append(pointA
)
148 localDerivativesO
= []
149 fltResOm1
= float(self
.resolutionO
- 1)
150 for i
in range(self
.resolutionO
):
151 par
= float(i
) / fltResOm1
153 pointO
= self
.splineO
.CalcPoint(par
)
154 worldPointsO
.append(worldMatrixO
@ pointO
)
156 derivativeO
= self
.splineO
.CalcDerivative(par
)
157 localDerivativesO
.append(derivativeO
)
160 currWorldMatrixA
= worldMatrixA
161 worldMatrixOInv
= worldMatrixO
.inverted()
162 prevDerivativeO
= localDerivativesO
[0]
163 for iO
in range(self
.resolutionO
):
164 currDerivativeO
= localDerivativesO
[iO
]
165 localRotMatO
= mathematics
.CalcRotationMatrix(prevDerivativeO
, currDerivativeO
)
167 currLocalAToLocalO
= worldMatrixOInv
@ currWorldMatrixA
169 for iA
in range(self
.resolutionA
):
170 pointALocalToO
= currLocalAToLocalO
@ localPointsA
[iA
]
171 rotatedPointA
= localRotMatO
@ pointALocalToO
172 worldPointsA
.append(worldMatrixO
@ rotatedPointA
)
175 worldPoint0A
= worldPointsA
[0]
176 for i
in range(self
.resolutionA
): worldOffsetsA
.append(worldPointsA
[i
] - worldPoint0A
)
179 for iA
in range(self
.resolutionA
):
180 iVert
= self
.vert0Index
+ (self
.resolutionA
* iO
) + iA
181 currVert
= worldPointsO
[iO
] + worldOffsetsA
[iA
]
182 self
.bMesh
.verts
[iVert
].co
= currVert
184 prevDerivativeO
= currDerivativeO
185 currWorldMatrixA
= worldMatrixO
@ localRotMatO
@ currLocalAToLocalO
189 bmVerts
= self
.bMesh
.verts
190 bmVerts
.ensure_lookup_table()
192 for iO
in range(self
.resolutionO
- 1):
193 for iA
in range(self
.resolutionA
- 1):
194 currIndexA1
= self
.vert0Index
+ (self
.resolutionA
* iO
) + iA
195 currIndexA2
= currIndexA1
+ 1
196 nextIndexA1
= self
.vert0Index
+ (self
.resolutionA
* (iO
+ 1)) + iA
197 nextIndexA2
= nextIndexA1
+ 1
199 self
.bMesh
.faces
.new([bmVerts
[currIndexA1
], bmVerts
[currIndexA2
], bmVerts
[nextIndexA2
], bmVerts
[nextIndexA1
]])
206 selObjects
= bpy
.context
.selected_objects
207 if len(selObjects
) != 2: raise Exception("len(selObjects) != 2") # shouldn't be possible
209 blenderActiveCurve
= bpy
.context
.active_object
210 blenderOtherCurve
= selObjects
[0]
211 if blenderActiveCurve
== blenderOtherCurve
: blenderOtherCurve
= selObjects
[1]
213 aCurve
= curves
.Curve(blenderActiveCurve
)
214 oCurve
= curves
.Curve(blenderOtherCurve
)
216 name
= "TODO: autoname"
218 return SweptSurface(aCurve
, oCurve
, name
)
221 def __init__(self
, activeCurve
, otherCurve
, name
= "SweptSurface"):
222 self
.curveA
= activeCurve
223 self
.curveO
= otherCurve
226 self
.nrSplines
= self
.curveA
.nrSplines
227 if self
.curveO
.nrSplines
< self
.nrSplines
: self
.nrSplines
= self
.curveO
.nrSplines
229 self
.bMesh
= bmesh
.new()
231 self
.splineSurfaces
= self
.SetupSplineSurfaces()
236 def SetupSplineSurfaces(self
):
237 rvSplineSurfaces
= []
240 for i
in range(self
.nrSplines
):
241 splineA
= self
.curveA
.splines
[i
]
242 splineO
= self
.curveO
.splines
[i
]
244 resA
= splineA
.resolution
245 resO
= splineO
.resolution
247 for iv
in range(resA
* resO
): self
.bMesh
.verts
.new()
249 splSurf
= SweptSplineSurface(splineA
, splineO
, self
.bMesh
, currV0Index
, resA
, resO
)
251 rvSplineSurfaces
.append(splSurf
)
253 currV0Index
+= resA
* resO
255 return rvSplineSurfaces
259 for splineSurface
in self
.splineSurfaces
: splineSurface
.Apply(self
.curveA
.worldMatrix
, self
.curveO
.worldMatrix
)
262 def AddToScene(self
):
263 mesh
= bpy
.data
.meshes
.new("Mesh" + self
.name
)
265 self
.bMesh
.to_mesh(mesh
)
268 meshObject
= bpy
.data
.objects
.new(self
.name
, mesh
)
270 bpy
.context
.collection
.objects
.link(meshObject
)
274 # profileSpline is swept over rail1Spline and scaled/rotated to have its endpoint on rail2Spline
275 class BirailedSplineSurface
:
276 def __init__(self
, rail1Spline
, rail2Spline
, profileSpline
, bMesh
, vert0Index
, resolutionRails
, resolutionProfile
):
277 self
.rail1Spline
= rail1Spline
278 self
.rail2Spline
= rail2Spline
279 self
.profileSpline
= profileSpline
282 self
.vert0Index
= vert0Index
283 self
.resolutionRails
= resolutionRails
284 self
.resolutionProfile
= resolutionProfile
287 def Apply(self
, worldMatrixRail1
, worldMatrixRail2
, worldMatrixProfile
):
288 localPointsProfile
= []
289 fltResProfilem1
= float(self
.resolutionProfile
- 1)
290 for i
in range(self
.resolutionProfile
):
291 par
= float(i
) / fltResProfilem1
292 pointProfile
= self
.profileSpline
.CalcPoint(par
)
293 localPointsProfile
.append(pointProfile
)
296 worldPointsRail1
= []
297 localDerivativesRail1
= []
298 worldPointsRail2
= []
299 fltResRailsm1
= float(self
.resolutionRails
- 1)
300 for i
in range(self
.resolutionRails
):
301 par
= float(i
) / fltResRailsm1
303 pointRail1
= self
.rail1Spline
.CalcPoint(par
)
304 worldPointsRail1
.append(worldMatrixRail1
@ pointRail1
)
306 derivativeRail1
= self
.rail1Spline
.CalcDerivative(par
)
307 localDerivativesRail1
.append(derivativeRail1
)
309 pointRail2
= self
.rail2Spline
.CalcPoint(par
)
310 worldPointsRail2
.append(worldMatrixRail2
@ pointRail2
)
313 currWorldMatrixProfile
= worldMatrixProfile
314 worldMatrixRail1Inv
= worldMatrixRail1
.inverted()
315 prevDerivativeRail1
= localDerivativesRail1
[0]
316 for iRail
in range(self
.resolutionRails
):
317 currDerivativeRail1
= localDerivativesRail1
[iRail
]
318 localRotMatRail1
= mathematics
.CalcRotationMatrix(prevDerivativeRail1
, currDerivativeRail1
)
320 currLocalProfileToLocalRail1
= worldMatrixRail1Inv
@ currWorldMatrixProfile
321 worldPointsProfileRail1
= []
322 for iProfile
in range(self
.resolutionProfile
):
323 pointProfileLocalToRail1
= currLocalProfileToLocalRail1
@ localPointsProfile
[iProfile
]
324 rotatedPointProfile
= localRotMatRail1
@ pointProfileLocalToRail1
325 worldPointsProfileRail1
.append(worldMatrixRail1
@ rotatedPointProfile
)
327 worldOffsetsProfileRail1
= []
328 worldPoint0ProfileRail1
= worldPointsProfileRail1
[0]
329 for iProfile
in range(self
.resolutionProfile
): worldOffsetsProfileRail1
.append(worldPointsProfileRail1
[iProfile
] - worldPoint0ProfileRail1
)
331 worldStartPointProfileRail1
= worldPointsRail1
[iRail
]
332 worldEndPointProfileRail1
= worldStartPointProfileRail1
+ worldOffsetsProfileRail1
[-1]
333 v3From
= worldEndPointProfileRail1
- worldStartPointProfileRail1
334 v3To
= worldPointsRail2
[iRail
] - worldStartPointProfileRail1
335 if not v3From
.magnitude
== 0:
336 scaleFactorRail2
= v3To
.magnitude
/ v3From
.magnitude
339 rotMatRail2
= mathematics
.CalcRotationMatrix(v3From
, v3To
)
341 worldOffsetsProfileRail2
= []
342 for iProfile
in range(self
.resolutionProfile
):
343 offsetProfileRail1
= worldOffsetsProfileRail1
[iProfile
]
344 worldOffsetsProfileRail2
.append(rotMatRail2
@ (offsetProfileRail1
* scaleFactorRail2
))
347 for iProfile
in range(self
.resolutionProfile
):
348 iVert
= self
.vert0Index
+ (self
.resolutionProfile
* iRail
) + iProfile
349 currVert
= worldPointsRail1
[iRail
] + worldOffsetsProfileRail2
[iProfile
]
350 self
.bMesh
.verts
[iVert
].co
= currVert
352 prevDerivativeRail1
= currDerivativeRail1
353 currWorldMatrixProfile
= worldMatrixRail1
@ localRotMatRail1
@ currLocalProfileToLocalRail1
357 bmVerts
= self
.bMesh
.verts
358 bmVerts
.ensure_lookup_table()
360 for iRail
in range(self
.resolutionRails
- 1):
361 for iProfile
in range(self
.resolutionProfile
- 1):
362 currIndex1
= self
.vert0Index
+ (self
.resolutionProfile
* iRail
) + iProfile
363 currIndex2
= currIndex1
+ 1
364 nextIndex1
= self
.vert0Index
+ (self
.resolutionProfile
* (iRail
+ 1)) + iProfile
365 nextIndex2
= nextIndex1
+ 1
367 self
.bMesh
.faces
.new([bmVerts
[currIndex1
], bmVerts
[currIndex2
], bmVerts
[nextIndex2
], bmVerts
[nextIndex1
]])
371 class BirailedSurface
:
374 selectedObjects
= bpy
.context
.selected_objects
376 rail1Curve
= curves
.Curve(selectedObjects
[0])
377 rail2Curve
= curves
.Curve(selectedObjects
[1])
378 profileCurve
= curves
.Curve(selectedObjects
[2])
380 name
= "BirailedSurface"
382 return BirailedSurface(rail1Curve
, rail2Curve
, profileCurve
, name
)
385 def __init__(self
, rail1Curve
, rail2Curve
, profileCurve
, name
= "BirailedSurface"):
386 self
.rail1Curve
= rail1Curve
387 self
.rail2Curve
= rail2Curve
388 self
.profileCurve
= profileCurve
391 self
.nrSplines
= self
.rail1Curve
.nrSplines
392 if self
.rail2Curve
.nrSplines
< self
.nrSplines
: self
.nrSplines
= self
.rail2Curve
.nrSplines
393 if self
.profileCurve
.nrSplines
< self
.nrSplines
: self
.nrSplines
= self
.profileCurve
.nrSplines
395 self
.bMesh
= bmesh
.new()
397 self
.splineSurfaces
= self
.SetupSplineSurfaces()
402 def SetupSplineSurfaces(self
):
403 rvSplineSurfaces
= []
406 for i
in range(self
.nrSplines
):
407 splineRail1
= self
.rail1Curve
.splines
[i
]
408 splineRail2
= self
.rail2Curve
.splines
[i
]
409 splineProfile
= self
.profileCurve
.splines
[i
]
411 resProfile
= splineProfile
.resolution
412 resRails
= splineRail1
.resolution
413 if splineRail2
.resolution
< resRails
: resRails
= splineRail2
.resolution
415 for iv
in range(resProfile
* resRails
): self
.bMesh
.verts
.new()
417 splSurf
= BirailedSplineSurface(splineRail1
, splineRail2
, splineProfile
, self
.bMesh
, currV0Index
, resRails
, resProfile
)
419 rvSplineSurfaces
.append(splSurf
)
421 currV0Index
+= resProfile
* resRails
423 return rvSplineSurfaces
427 for splineSurface
in self
.splineSurfaces
: splineSurface
.Apply(self
.rail1Curve
.worldMatrix
, self
.rail2Curve
.worldMatrix
, self
.profileCurve
.worldMatrix
)
430 def AddToScene(self
):
431 mesh
= bpy
.data
.meshes
.new("Mesh" + self
.name
)
433 self
.bMesh
.to_mesh(mesh
)
436 meshObject
= bpy
.data
.objects
.new(self
.name
, mesh
)
438 bpy
.context
.collection
.objects
.link(meshObject
)