GSOF-3dWireFrame 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. GSOF_3dWireFrame/Example_F16.py +141 -0
  2. GSOF_3dWireFrame/Example_dynamicWorld.py +99 -0
  3. GSOF_3dWireFrame/Example_motionWorld.py +75 -0
  4. GSOF_3dWireFrame/Example_staticWorld.py +112 -0
  5. GSOF_3dWireFrame/F16_Class.py +163 -0
  6. GSOF_3dWireFrame/Lib3D/Assembly.py +72 -0
  7. GSOF_3dWireFrame/Lib3D/Lib3D.py +145 -0
  8. GSOF_3dWireFrame/Lib3D/Object_WireFrame.py +66 -0
  9. GSOF_3dWireFrame/Lib3D/Object_base.py +122 -0
  10. GSOF_3dWireFrame/Lib3D/Objects.py +91 -0
  11. GSOF_3dWireFrame/Lib3D/Utils.py +9 -0
  12. GSOF_3dWireFrame/Lib3D/WireFrame_display.py +37 -0
  13. GSOF_3dWireFrame/Lib3D/__init__.py +7 -0
  14. GSOF_3dWireFrame/Lib3D/stlToObj.py +40 -0
  15. GSOF_3dWireFrame/MathLib/MathLib.py +460 -0
  16. GSOF_3dWireFrame/MathLib/__init__.py +7 -0
  17. GSOF_3dWireFrame/attitudeViewer.py +5 -0
  18. GSOF_3dWireFrame/modules/AttitudeViewer_class.py +115 -0
  19. GSOF_3dWireFrame/modules/Controls.py +60 -0
  20. GSOF_3dWireFrame/modules/__init__.py +7 -0
  21. GSOF_3dWireFrame/objects/Axis.json +40 -0
  22. GSOF_3dWireFrame/objects/F16.stl +0 -0
  23. GSOF_3dWireFrame/objects/LandingGear.json +28 -0
  24. GSOF_3dWireFrame/objects/Plume.json +34 -0
  25. GSOF_3dWireFrame/objects/Spark.json +15 -0
  26. GSOF_3dWireFrame/objects/cube.json +31 -0
  27. GSOF_3dWireFrame/objects/cube_flex.json +31 -0
  28. GSOF_3dWireFrame/objects/frame.json +16 -0
  29. GSOF_3dWireFrame/objects/house.json +50 -0
  30. GSOF_3dWireFrame/objects/net.json +3 -0
  31. GSOF_3dWireFrame/objects/plane.stl +0 -0
  32. GSOF_3dWireFrame/objects/pyramid.json +22 -0
  33. GSOF_3dWireFrame/stlToObject.py +32 -0
  34. gsof_3dwireframe-1.0.0.dist-info/METADATA +48 -0
  35. gsof_3dwireframe-1.0.0.dist-info/RECORD +39 -0
  36. gsof_3dwireframe-1.0.0.dist-info/WHEEL +5 -0
  37. gsof_3dwireframe-1.0.0.dist-info/licenses/AUTHORS +1 -0
  38. gsof_3dwireframe-1.0.0.dist-info/licenses/LICENSE +7 -0
  39. gsof_3dwireframe-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/python
2
+ """
3
+ * Example_F16.py
4
+ * Created on: 31 May 2026
5
+ * Improved for: 31 May 2026
6
+ * Author: Guy Soffer
7
+ * Copyright (C) 2026 Guy Soffer
8
+ """
9
+ import pygame, math
10
+ from Lib3D.Object_WireFrame import Object_wireFrame
11
+ from Lib3D.Assembly import Assembly
12
+ #from Lib3D.Object_base import Object_base
13
+ from Lib3D import Objects
14
+ from Lib3D import WireFrame_display as DISP
15
+ from F16_Class import F16_View, Commands, State
16
+
17
+ SCREEN_WIDTH = 800
18
+ SCREEN_HEIGHT = 600
19
+ WHITE = (255,255,255)
20
+ BLUE = (220,220,255)
21
+ BLACK = (0,0,0)
22
+ RED = (255,0,0)
23
+ GREEN = (0,255,0)
24
+ PI = math.pi
25
+
26
+ def drawWireFrame(screen, obj, color=None) -> None:
27
+ for line in obj.getLines():
28
+ x0, y0, z0 = line.p0
29
+ x1, y1, z1 = line.p1
30
+ lcolor = color
31
+ if lcolor == None:
32
+ lcolor = line.color
33
+ pygame.draw.line( screen, lcolor, (x0, y0), (x1, y1) ) #< Line from P0 to P1
34
+
35
+ def clearScreen(screen, color=(255,255,255)) -> None:
36
+ screen.fill(color)
37
+
38
+ def newScreen(title="New", resX=SCREEN_WIDTH, resY=SCREEN_HEIGHT, color=WHITE):
39
+ screenSize = (resX, resY)
40
+ screen = pygame.display.set_mode( screenSize )
41
+ clearScreen(screen, color)
42
+ pygame.display.set_caption(title)
43
+ return screen
44
+
45
+ if __name__ == "__main__":
46
+ import copy
47
+ ground = Object_wireFrame(
48
+ obj=Objects.net(25,25), color=(0,100,0))\
49
+ .scale(0.2)\
50
+ .rotate(x=math.pi/2, y=0, z=0)\
51
+ .translate(-250, -200, -250)\
52
+ .setOrigin()
53
+
54
+ f16 = F16_View()\
55
+ .scale(1.0)\
56
+ .translate(100, 100, -100).setOrigin()
57
+ f16.plane.color = BLACK
58
+
59
+ rotateBy = (0*3.14/4, 1*3.14/8, 0)
60
+ f16_1 = copy.deepcopy(f16)
61
+ f16_1.rotate(*rotateBy, centerAt=(100,100,-100))\
62
+ .setOrigin()
63
+ f16_1.plane.color = RED
64
+
65
+ rotateBy = (0*3.14/4, -1*3.14/8, 0)
66
+ f16_2 = copy.deepcopy(f16)
67
+ f16_2.translate(-100, -100, 100)\
68
+ .rotate(*rotateBy)\
69
+ .translate(100, 100, -100)\
70
+ .translate(-100, 0, 100)\
71
+ .setOrigin()
72
+ f16_2.plane.color = GREEN
73
+
74
+ world = Assembly(objects=(ground, f16, f16_1, f16_2))
75
+
76
+ pygame.init()
77
+ clock = pygame.time.Clock()
78
+ screen = newScreen("3D Wire Frame Shapes", SCREEN_WIDTH, SCREEN_HEIGHT, WHITE)
79
+ wireframe = DISP.WireFrame(screen, pygame.draw.line, f=50, scale=20.0)
80
+
81
+ fps = 30
82
+ dt = 1/fps
83
+ t = 0.0
84
+ camAngX_r = 0.0
85
+ camAngY_r = 0.0
86
+ camAngZ_r = 0.0
87
+ commands = Commands()
88
+ mPosZ = 0.0
89
+ state = State(thrust_lbf=6000)
90
+ useMouse = True
91
+
92
+ run = True
93
+ while run:
94
+ for event in pygame.event.get():
95
+ if event.type == pygame.QUIT:
96
+ run = False
97
+ ### Wait for next step time
98
+ keys = pygame.key.get_pressed()
99
+ state.thrust_lbf += (keys[pygame.K_q] -keys[pygame.K_a])*200
100
+ commands.gearsDown_b += keys[pygame.K_b] -keys[pygame.K_g]
101
+ commands.gearsDown_b = min(1, max(0,commands.gearsDown_b))
102
+ state.wowNose_b = bool(keys[pygame.K_2])
103
+ state.wowLeft_b = bool(keys[pygame.K_1])
104
+ state.wowRight_b = bool(keys[pygame.K_3])
105
+ print(state.wowLeft_b, state.wowNose_b, state.wowRight_b)
106
+
107
+ if useMouse:
108
+ (mPosX, mPosY) = pygame.mouse.get_pos()
109
+ mPosZ += (keys[pygame.K_z] -keys[pygame.K_x])*2
110
+ x = mPosX/SCREEN_WIDTH -0.5
111
+ y = mPosY/SCREEN_HEIGHT -0.5
112
+ z = mPosZ/360
113
+ else:
114
+ x += 0.5*dt
115
+ y += 1*dt
116
+ z = 0
117
+ commands.rudder_d = z*30
118
+ commands.leftAliron_d = -25*x
119
+ commands.rightAliron_d = 25*x
120
+ commands.leftElevator = 0.5*commands.leftAliron_d +25*y
121
+ commands.rightElevator = 0.5*commands.rightAliron_d +25*y
122
+ camAngX_r = y*PI
123
+ camAngY_r = z*PI
124
+ camAngZ_r = x*PI
125
+
126
+ world.reset()
127
+ f16.setControls(t, commands, state)
128
+ world.transform(rotate=(camAngX_r,camAngY_r,camAngZ_r), translate=(0,0,-1000))
129
+ #world.transform(rotate=(3.14/2, 0.0*3.14, 0), translate=(0,0,-1000))
130
+
131
+ ### Draw 3D world
132
+ clearScreen(screen, BLUE)
133
+ wireframe.draw(world)
134
+
135
+ t += dt
136
+ clock.tick(30)
137
+
138
+ ### Display output
139
+ pygame.display.flip()
140
+
141
+ pygame.quit()
@@ -0,0 +1,99 @@
1
+ import pygame, math
2
+ from Lib3D.Object_WireFrame import Object_wireFrame as Object
3
+ from Lib3D.Assembly import Assembly
4
+ from Lib3D import WireFrame_display as DISP
5
+
6
+ SCREEN_WIDTH = 800
7
+ SCREEN_HEIGHT = 600
8
+ WHITE = (255,255,255)
9
+ YELLOW = (240,240,150)
10
+ BLACK = (0,0,0)
11
+ PI = math.pi
12
+
13
+ def clearScreen(screen, color=(255,255,255)) -> None:
14
+ screen.fill(color)
15
+
16
+ def newScreen(title="New", resX=SCREEN_WIDTH, resY=SCREEN_HEIGHT, color=WHITE):
17
+ screenSize = (resX, resY)
18
+ screen = pygame.display.set_mode( screenSize )
19
+ clearScreen(screen, color)
20
+ pygame.display.set_caption(title)
21
+ return screen
22
+
23
+ if __name__ == "__main__":
24
+ import json
25
+ d = 4
26
+ solidHouse = Object(filename="./objects/house.json", color=(0,180,180), name="House").scale(10.0).setOrigin()
27
+ window = Object(filename="./objects/frame.json", color=(200,0,0), name="Window").setCenter(scale=0.8)
28
+ flexHouse = Assembly(objects = (
29
+ Object(filename="./objects/cube.json", color=(190,190,190), name="Body").translate(0,0,0 +d).setOrigin(),
30
+ Object(filename="./objects/pyramid.json", color=(90,90,90), name="Roof").translate(0,-2.5,0 +d).setOrigin(),
31
+ Assembly(objects=(window,), name="Window-Assy").translate(0,0,-1 +d).setOrigin(),
32
+ ),
33
+ connections=[
34
+ [[0,4],[1,0]], #< Point-4 of object-0 to point-0 of object-1
35
+ [[0,5],[1,1]], #< Point-5 of object-0 to point-1 of object-1
36
+ [[0,6],[1,2]], #< Point-6 of object-0 to point-2 of object-1
37
+ [[0,7],[1,3]] #< Point-7 of object-0 to point-3 of object-1
38
+ ],
39
+ name="Flex-House"
40
+ ).scale(10).rotate(PI,0,0).setOrigin()
41
+
42
+ world = Assembly(objects = (
43
+ solidHouse.translate(0,0,0).setOrigin(),
44
+ flexHouse.translate(0,-0,0).setOrigin(),
45
+ ))
46
+ pygame.init()
47
+ clock = pygame.time.Clock()
48
+ screen = newScreen("3D Wire Frame Shapes", SCREEN_WIDTH, SCREEN_HEIGHT, WHITE)
49
+ wireframe = DISP.WireFrame(screen, pygame.draw.line, f=50, scale=80)
50
+ fps = 30
51
+ dt = 1/fps
52
+ t = 0.0
53
+ camAngX_r = 0.0
54
+ camAngY_r = 0.0
55
+ roofAng_r = 0.0
56
+ houseAng_r = 0.0
57
+ useMouse = True
58
+
59
+ run = True
60
+ while run:
61
+ ### Get inputs
62
+ for event in pygame.event.get():
63
+ if event.type == pygame.QUIT:
64
+ run = False
65
+
66
+ ### Calculate next step state
67
+ camAngX_r += 0.5*dt
68
+ camAngY_r += 1*dt
69
+ roofAng_r = (PI/4/2)*math.sin(2*PI*1*t)
70
+ houseAng_r = (PI/4)*math.sin(2*PI*1.5*t)
71
+ t += dt
72
+
73
+ ### Update 3D world
74
+ world.reset()
75
+ solidHouse.rotate(x=0,y=roofAng_r,z=houseAng_r)
76
+ roof = flexHouse.objects[1]
77
+ roof.rotate(x=0,y=roofAng_r,z=0)
78
+ window.rotate(x=0,y=0,z=10*t)
79
+ world.rotate(x=camAngX_r,y=camAngY_r,z=0)
80
+ world.translate(x=0,y=0,z=-600)
81
+
82
+ ### Draw 3D world
83
+ clearScreen(screen, YELLOW)
84
+ wireframe.draw(world)
85
+
86
+ ### Wait for next step time
87
+ if useMouse:
88
+ (mPosX, mPosY) = pygame.mouse.get_pos()
89
+ camAngY_r = 0.01*(mPosX -SCREEN_WIDTH/2)
90
+ camAngX_r = 0.01*(mPosY -SCREEN_HEIGHT/2)
91
+ else:
92
+ camAngX_r += 0.5*dt
93
+ camAngY_r += 1*dt
94
+ clock.tick(30)
95
+
96
+ ### Display output
97
+ pygame.display.flip()
98
+
99
+ pygame.quit()
@@ -0,0 +1,75 @@
1
+ import pygame
2
+ from Lib3D.Object_WireFrame import Object_wireFrame as Object
3
+ from Lib3D.Assembly import Assembly
4
+ from Lib3D import Objects
5
+ from Lib3D import WireFrame_display as DISP
6
+ from modules import Controls
7
+
8
+ SCREEN_WIDTH = 800
9
+ SCREEN_HEIGHT = 600
10
+ WHITE = (255,255,255)
11
+ BLACK = (0,0,0)
12
+
13
+ def clearScreen(screen, color=(255,255,255)) -> None:
14
+ screen.fill(color)
15
+
16
+ def newScreen(title="New", resX=SCREEN_WIDTH, resY=SCREEN_HEIGHT, color=WHITE):
17
+ screenSize = (resX, resY)
18
+ screen = pygame.display.set_mode( screenSize )
19
+ clearScreen(screen, color)
20
+ pygame.display.set_caption(title)
21
+ return screen
22
+
23
+ if __name__ == "__main__":
24
+ house = Object(filename="./objects/house.json", color=(0,180,180))
25
+ world = Assembly(objects = (
26
+ house,
27
+ ))
28
+
29
+ pygame.init()
30
+ clock = pygame.time.Clock()
31
+ screen = newScreen("3D Wire Frame Shapes", SCREEN_WIDTH, SCREEN_HEIGHT, WHITE)
32
+ wireframe = DISP.WireFrame(screen, pygame.draw.line, f=50, scale=10)
33
+ viewer = Controls.Viewer( pos=(0,0,-400),
34
+ center=(int(screen.get_width()/2), int(screen.get_height()/2)),
35
+ moveLeftKey = pygame.K_a,
36
+ moveRightKey = pygame.K_d,
37
+ moveUpKey = pygame.K_UP,
38
+ moveDownKey = pygame.K_DOWN,
39
+ moveFwdKey = pygame.K_w,
40
+ moveBackKey = pygame.K_x,
41
+ tiltLeft = pygame.K_COMMA,
42
+ tiltRight = pygame.K_PERIOD
43
+ )
44
+
45
+ fps = 30
46
+ dt = 1/fps
47
+ t = 0.0
48
+ run = True
49
+
50
+ while run:
51
+ for event in pygame.event.get():
52
+ if event.type == pygame.QUIT:
53
+ run = False
54
+
55
+ keys = pygame.key.get_pressed()
56
+ (mPosX, mPosY) = pygame.mouse.get_pos()
57
+ wireframe.f += -(keys[pygame.K_1] - keys[pygame.K_2])*10
58
+ viewer.update(keys, mPosX, mPosY, speed=2)
59
+
60
+ clearScreen(screen, WHITE)
61
+ world.reset()
62
+ world.translate(*viewer.getPosition())
63
+ world.rotate(*viewer.getAttitude())
64
+
65
+ ### Draw 3D world
66
+ clearScreen(screen, WHITE)
67
+ wireframe.draw(world)
68
+
69
+ ### Wait for next step time
70
+ clock.tick(30)
71
+
72
+ ### Display output
73
+ pygame.display.flip()
74
+
75
+ pygame.quit()
@@ -0,0 +1,112 @@
1
+ import pygame, math
2
+ from Lib3D.Object_WireFrame import Object_wireFrame as Object
3
+ from Lib3D.Object_base import Object_base
4
+ from Lib3D.Assembly import Assembly
5
+ from Lib3D import WireFrame_display as DISP
6
+ from Lib3D import Objects
7
+
8
+ SCREEN_WIDTH = 800
9
+ SCREEN_HEIGHT = 600
10
+ WHITE = (255,255,255)
11
+ BLACK = (0,0,0)
12
+ PI = math.pi
13
+
14
+ def drawWireFrame(screen, obj, color=None) -> None:
15
+ for line in obj.getLines():
16
+ x0, y0, z0 = line.p0
17
+ x1, y1, z1 = line.p1
18
+ lcolor = color
19
+ if lcolor == None:
20
+ lcolor = line.color
21
+ pygame.draw.line( screen, lcolor, (x0, y0), (x1, y1) ) #< Line from P0 to P1
22
+
23
+ def clearScreen(screen, color=(255,255,255)) -> None:
24
+ screen.fill(color)
25
+
26
+ def newScreen(title="New", resX=SCREEN_WIDTH, resY=SCREEN_HEIGHT, color=WHITE):
27
+ screenSize = (resX, resY)
28
+ screen = pygame.display.set_mode( screenSize )
29
+ clearScreen(screen, color)
30
+ pygame.display.set_caption(title)
31
+ return screen
32
+
33
+ if __name__ == "__main__":
34
+ ### 1. Build the ground
35
+ net = Object(obj=Objects.net(25,20), color=(0,100,0), name="NET")\
36
+ .setCenter(pos=(0,0,0), rotate=(PI/2, 0, 0), scale=0.2 )
37
+ axis1 = Object(filename="./objects/axis.json", color=(10,10,10), name="WorldAxis" )\
38
+ .scale(100.0)\
39
+ .setOrigin()
40
+ ground = Assembly(objects=(net, axis1), name="Ground").translate(-200, 0, 0).setOrigin()
41
+
42
+ ### 2. Build the sun
43
+ sun = Object(obj=Objects.sphere(500, 15, color=(225,220,50)), name="SUN")
44
+ sun.setCenter(scale=0.15, rotate=(PI/2,0,0))
45
+ sun.translate(0, 250, 300) #< More up (Y) and forward (Z) to the center of the net
46
+ sun.setOrigin()
47
+
48
+ ### 3. Build the plane
49
+ axis2 = Object(
50
+ filename="./objects/axis.json", color=(10,10,10 ))\
51
+ .scale(100.0)\
52
+ .setOrigin()
53
+ f16 = Object(filename="./objects/F16.stl", color=(0,0,255), name="F16")\
54
+ .setCenter(scale=1.0, rotate=(0,-PI/2,0), method="arithCenter")
55
+ plane = Assembly(objects=[f16, axis2], name="Plane")\
56
+ .rotate(0.5*-3.14/2,0,0)\
57
+ .translate(0,250,0)\
58
+ .setOrigin()
59
+
60
+ ### 4. Build the world
61
+ world = Assembly(objects = (
62
+ ground,
63
+ plane,
64
+ sun,
65
+ ), name="World")
66
+
67
+ pygame.init()
68
+ clock = pygame.time.Clock()
69
+ screen = newScreen("3D Wire Frame Shapes", SCREEN_WIDTH, SCREEN_HEIGHT, WHITE)
70
+ wireframe = DISP.WireFrame(screen, pygame.draw.line, f=50, scale=10.0)
71
+
72
+ fps = 30
73
+ dt = 1/fps
74
+ t = 0.0
75
+ camAngX_r = 0.0
76
+ camAngY_r = 0.0
77
+ f16Ang_r = 0.0
78
+ useMouse = True
79
+
80
+ run = True
81
+ while run:
82
+ for event in pygame.event.get():
83
+ if event.type == pygame.QUIT:
84
+ run = False
85
+
86
+ world.reset()
87
+ #world.rotate(x=1.8,y=3.14,z=0.3)
88
+ world.rotate(x=camAngX_r,y=camAngY_r,z=0)
89
+ #world.rotate(x=camAngX_r,y=camAngY_r,z=0)
90
+ f16.rotate(0, f16Ang_r, 0)
91
+ world.translate(x=0,y=0,z=-1000)
92
+
93
+ ### Draw 3D world
94
+ clearScreen(screen, WHITE)
95
+ wireframe.draw(world)
96
+
97
+ ### Wait for next step time
98
+ if useMouse:
99
+ (mPosX, mPosY) = pygame.mouse.get_pos()
100
+ camAngY_r = 0.01*(mPosX -SCREEN_WIDTH/2)
101
+ camAngX_r = 0.01*(mPosY -SCREEN_HEIGHT/2)
102
+ else:
103
+ camAngX_r += 0.5*dt
104
+ camAngY_r += 1*dt
105
+ f16Ang_r += 4*dt
106
+ t += dt
107
+ clock.tick(30)
108
+
109
+ ### Display output
110
+ pygame.display.flip()
111
+
112
+ pygame.quit()
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/python
2
+ """
3
+ * F16_Class.py
4
+ * Created on: 6 Jan 2025
5
+ * Improved for: 25 May 2026
6
+ * Author: Guy Soffer
7
+ * Copyright (C) 2026 Guy Soffer
8
+ """
9
+
10
+ from math import pi
11
+ try:
12
+ from GSOF_3dWireFrame.Lib3D.Object_WireFrame import Object_wireFrame as Object
13
+ from GSOF_3dWireFrame.Lib3D.Object_base import Object_base
14
+ from GSOF_3dWireFrame.Lib3D.Assembly import Assembly
15
+ from GSOF_3dWireFrame.Lib3D import Objects
16
+ _3D_active = True
17
+ except:
18
+ _3D_active = False
19
+ print("GSOF_Wireframe3D module isn't installed")
20
+
21
+ degToRad = pi/180
22
+ #YELLOW = (255,255,140)
23
+ YELLOW = (125,125,0)
24
+ BLACK = (0,0,0)
25
+ RED = (255,0,0)
26
+ GREEN = (0,170,0)
27
+ BLUE = (0,0,255)
28
+ GRAY = (50,50,50)
29
+
30
+ class State():
31
+ def __init__(self,
32
+ azimuth_d=0,
33
+ pitch_d=0,
34
+ roll_d=0,
35
+ thrust_lbf=0,
36
+ wowNose_b=False,
37
+ wowLeft_b=False,
38
+ wowRight_b=False):
39
+ self.azimuth_d = azimuth_d
40
+ self.pitch_d = pitch_d
41
+ self.roll_d = roll_d
42
+ self.thrust_lbf = thrust_lbf
43
+ self.wowNose_b = wowNose_b
44
+ self.wowLeft_b = wowLeft_b
45
+ self.wowRight_b = wowRight_b
46
+
47
+ class Commands():
48
+ def __init__(self,
49
+ leftAliron_d=0, rightAliron_d=0,
50
+ leftElevator_d=0, rightElevator_d=0,
51
+ rudder_d=0, speedbrake_d=0,
52
+ throttle=0,
53
+ gearsDown_b=True):
54
+ self.leftAliron_d = leftAliron_d
55
+ self.rightAliron_d = rightAliron_d
56
+ self.leftElevator_d = leftElevator_d
57
+ self.rightElevator_d = rightElevator_d
58
+ self.rudder_d = rudder_d
59
+ self.speedbrake_d = speedbrake_d
60
+ self.gearsDown_b = gearsDown_b
61
+
62
+ class F16_View(Assembly):
63
+ """Constructs the gauges screen"""
64
+ def __init__(self, folder='./'):
65
+ self.time = 0.0
66
+ axis = Object(
67
+ filename="%s/objects/axis.json"%folder, color=GREEN)\
68
+ .scale(50.0)\
69
+ .translate(0, 0, 150)\
70
+ .setOrigin()
71
+
72
+ self.plane = Object(
73
+ filename="%s/objects/f16.stl"%folder, color=BLUE, name="F16")\
74
+ .setCenter(scale=1.0, method="arithCenter")
75
+
76
+ self.plume = objects=Object(
77
+ filename="%s/objects/Plume.json"%folder, color=RED)\
78
+ .setCenter(scale=30, rotate=(180*degToRad, 0, 0))
79
+ plume = Assembly(objects=(self.plume,))
80
+ plume.translate(0, 0, -90).setOrigin()
81
+
82
+ self.nw = Object(
83
+ filename="%s/objects/LandingGear.json"%folder, color=BLACK, name="NW")
84
+ self.nwow = Object(
85
+ filename="%s/objects/Spark.json"%folder, color=YELLOW, name="NWOW")
86
+ nw = Assembly(objects=(self.nw, self.nwow), name="NW-Assy")\
87
+ .translate(0, -2, 0).scale(8).translate(0, -30, 80).setOrigin()
88
+
89
+ self.lw = Object(
90
+ filename="%s/objects/LandingGear.json"%folder, color=BLACK, name="LW")
91
+ self.lwow = Object(
92
+ filename="%s/objects/Spark.json"%folder, color=YELLOW)
93
+ lw = Assembly(objects=(self.lw, self.lwow), name="LW-Assy")\
94
+ .translate(0, -2, 0).rotate(x=0, y=0, z=degToRad*15)\
95
+ .scale(8).translate(18, -30, 0).setOrigin()
96
+
97
+ self.rw = Object(
98
+ filename="%s/objects/LandingGear.json"%folder, color=BLACK, name="RW")
99
+ self.rwow = Object(
100
+ filename="%s/objects/Spark.json"%folder, color=YELLOW)
101
+ rw = Assembly(objects=(self.rw, self.rwow), name="RW-Assy")\
102
+ .translate(0, -2, 0).rotate(x=0, y=0, z=-degToRad*15)\
103
+ .scale(8).translate(-18, -30, 0).setOrigin()
104
+
105
+ self.gears = Assembly(objects=(nw,
106
+ rw,
107
+ lw
108
+ ))
109
+ super().__init__(objects=(axis, self.plane, plume, self.gears))
110
+
111
+ def setControls(self, time, commands=None, state=None):
112
+ """Update all elements"""
113
+ self.time += 0.1
114
+
115
+ if state != None:
116
+ self.setWOW(state.wowNose_b, state.wowLeft_b, state.wowRight_b)
117
+ self.setExahustPlume(state.thrust_lbf)
118
+ heading = state.azimuth_d*degToRad
119
+ pitch = -state.pitch_d*degToRad
120
+ roll = state.roll_d*degToRad
121
+ self.setAttitude(heading, pitch, roll)
122
+
123
+ if commands != None:
124
+ self.setFCS(commands.leftAliron_d,
125
+ commands.rightAliron_d,
126
+ commands.leftElevator_d,
127
+ commands.rightElevator_d,
128
+ commands.rudder_d,
129
+ commands.speedbrake_d)
130
+ self.setGearsDown(commands.gearsDown_b)
131
+
132
+ def setAttitude(self, heading, pitch, roll) -> None:
133
+ self.rotate( y=-heading, x=-pitch, z=-roll )
134
+
135
+ def setExahustPlume(self, thrust_lbf) -> None:
136
+ thrustMAX = 6360
137
+ plume = thrust_lbf/thrustMAX
138
+ if plume > 1:
139
+ plume = 1
140
+ elif plume < 0:
141
+ plume = 0
142
+ plumeColor = (255, 255*(1-plume), 255*(1-plume))
143
+ self.plume.rotate(x=0, y=0, z=self.time*plume)
144
+ self.plume.scale(plume).color = plumeColor
145
+
146
+ def setFCS(self, lAliron_deg, rAliron_deg, lElevator, rElevator, rudder_deg, sb_deg) -> None:
147
+ return
148
+
149
+ def setGearsDown(self, downCmd) -> None:
150
+ if downCmd == False:
151
+ self.gears.scale(0.0)
152
+ else:
153
+ self.gears.scale(1.0)
154
+
155
+ def setWOW(self, nose, left, right) -> None:
156
+ time = int(self.time*10)
157
+ blink = bool(time&0b010)
158
+ self.nwow.rotate(x=0, y=0, z=4*self.time)\
159
+ .scale(int(nose and blink))
160
+ self.lwow.rotate(x=0, y=0, z=4*self.time)\
161
+ .scale(int(left and blink))
162
+ self.rwow.rotate(x=0, y=0, z=4*self.time)\
163
+ .scale(int(right and blink))
@@ -0,0 +1,72 @@
1
+ from GSOF_3dWireFrame.Lib3D import Lib3D as L
2
+ from GSOF_3dWireFrame.Lib3D.Object_base import Object_base
3
+
4
+
5
+ class Assembly(Object_base):
6
+ ASSY_NUM = 0
7
+ """A new frame of reference with collection of other assemblies or objects"""
8
+ def __init__(self,
9
+ objects=[], #< Objects in assembly
10
+ connections=[], #< Connections between objects (for flexable objects)
11
+ name=None
12
+ ):
13
+ self.objects = objects
14
+ self.connections = connections
15
+ if name == None:
16
+ name = "A" +str(Assembly.ASSY_NUM)
17
+ Assembly.ASSY_NUM += 1
18
+ self.name = name
19
+ super().__init__()
20
+
21
+ def reset(self, all=True):
22
+ """Reset current state and all objects (optional)"""
23
+ super().reset()
24
+ if all:
25
+ for obj in self.objects:
26
+ obj.reset(all)
27
+ return self
28
+
29
+ def findCenter(self, method) -> list:
30
+ """Return the center point of the assembly"""
31
+ points = self.getLines()
32
+ return super()._findCenter(points, method)
33
+
34
+ def getObjects(self) -> list:
35
+ """Return a list of all objects"""
36
+ objects = []
37
+ for obj in self.objects:
38
+ objects += obj.getObjects()
39
+ return objects
40
+
41
+ def getLines(self):
42
+ """Return lines of all objects. Will update transformations if needed"""
43
+ lines = []
44
+ if not self.isUpdated():
45
+ self.update()
46
+
47
+ ### Lines from all objects
48
+ for obj in self.objects:
49
+ lines += obj.getLines()
50
+
51
+ ### Lines between objects
52
+ #print("\n", self.name +":") if len(self.connections) > 0 else None
53
+ for between in self.connections:
54
+ [obj0, p0], [obj1, p1] = between
55
+ fromPnt = self.objects[obj0].newPoints[p0]
56
+ toPnt = self.objects[obj1].newPoints[p1]
57
+ lines += [L.Line(fromPnt, toPnt)]
58
+ ## if False:
59
+ ## print("CON: ", obj0, p0, obj1, p1)
60
+ ## print(self.objects[obj0].name, self.objects[obj1].name)
61
+ ## print(fromPnt, toPnt)
62
+ return lines
63
+
64
+ def update(self):
65
+ """Update the coordinates of all assembly and object"""
66
+ #print("Update: %s"%self.name)
67
+ for obj in self.objects:
68
+ #print("%s.%s"%(self.name,obj.name))
69
+ if not self.isUpdated():
70
+ obj.transform(transMatrix=self.state)
71
+ obj.update()
72
+ self.stateTouched = False