forked from adamredwoods/minib3d-monkey
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tpick.monkey
259 lines (175 loc) · 5.65 KB
/
tpick.monkey
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
''NOTES
'' needs TCollision to be ported over
Import minib3d
Import minib3d.math.geom
Import minib3d.tcollision
Class TPick
' EntityPickMode in TEntity
Const EPSILON=.0001
Global ent_list:List<TEntity>=New List<TEntity> ' list containing pickable entities
Global picked_x:Float,picked_y:Float,picked_z:Float
Global picked_nx:Float,picked_ny:Float,picked_nz:Float
Global picked_time:Float
Global picked_ent:TEntity
Global picked_surface:Int = -1
Global picked_triangle:Int
Global mat:Matrix=New Matrix
Global tform:TransformMat = New TransformMat()
Function CameraPick:TEntity(cam:TCamera,vx:Float,vy:Float)
Local vec:Vector
Local dvec:Vector
vy=cam.viewport[3]-vy
vec = cam.GluUnProject(vx,vy,0.0,cam)
dvec = cam.GluUnProject(vx,vy,1.0,cam)
Return Pick(vec.x,vec.y,-vec.z,dvec.x,dvec.y,-dvec.z,0.0)
End
Function EntityPick:TEntity(ent:TEntity,range:Float)
TEntity.TFormPoint(0.0,0.0,0.0,ent,Null)
Local x:Float=TEntity.TFormedX()
Local y:Float=TEntity.TFormedY()
Local z:Float=TEntity.TFormedZ()
TEntity.TFormPoint(0.0,0.0,range,ent,Null)
Local x2:Float=TEntity.TFormedX()
Local y2:Float=TEntity.TFormedY()
Local z2:Float=TEntity.TFormedZ()
Return Pick(x,y,z,x2,y2,z2)
End
Function LinePick:TEntity(x:Float,y:Float,z:Float,dx:Float,dy:Float,dz:Float,radius:Float=0.0)
Return Pick(x,y,z,x+dx,y+dy,z+dz,radius)
End
Function EntityVisible(src_ent:TEntity,dest_ent:TEntity)
' get pick values
Local px:Float=picked_x
Local py:Float=picked_y
Local pz:Float=picked_z
Local pnx:Float=picked_nx
Local pny:Float=picked_ny
Local pnz:Float=picked_nz
Local ptime:Float=picked_time
Local pent:TEntity=picked_ent
Local psurf:TSurface=picked_surface
Local ptri=picked_triangle
' perform line pick
Local ax:Float=src_ent.EntityX(True)
Local ay:Float=src_ent.EntityY(True)
Local az:Float=src_ent.EntityZ(True)
Local bx:Float=dest_ent.EntityX(True)
Local by:Float=dest_ent.EntityY(True)
Local bz:Float=dest_ent.EntityZ(True)
Local pick:TEntity=Pick(ax,ay,az,bx,by,bz)
' if picked entity was dest ent then dest_picked flag to true
Local dest_picked=False
If picked_ent=dest_ent Then dest_picked=True
' restore pick values
picked_x=px
picked_y=py
picked_z=pz
picked_nx=pnx
picked_ny=pny
picked_nz=pnz
picked_time=ptime
picked_ent=pent
picked_surface=psurf
picked_triangle=ptri
' return false (not visible) if nothing picked, or dest ent wasn't picked
If pick<>Null And dest_picked<>True
Return False
Endif
Return True
End
Function PickedX:Float()
Return picked_x
End
Function PickedY:Float()
Return picked_y
End
Function PickedZ:Float()
Return picked_z
End
Function PickedNX:Float()
Return picked_nx
End
Function PickedNY:Float()
Return picked_ny
End
Function PickedNZ:Float()
Return picked_nz
End
Function PickedTime:Float()
Return picked_time
End
Function PickedEntity:TEntity()
Return picked_ent
End
Function PickedSurface:TSurface()
If picked_surface <0 Or Not picked_ent Then Return Null
Return TMesh(picked_ent).GetSurface(picked_surface)
End
Function PickedTriangle()
Return picked_triangle
End
Global vec_a:Vector =New Vector(0.0,0.0,0.0)
Global vec_b:Vector =New Vector(0.0,0.0,0.0)
Global vec_radius:Vector =New Vector(0.0,0.0,0.0)
Global vec_i:Vector =New Vector(0.0,0.0,0.0)
Global vec_j:Vector =New Vector(0.0,0.0,0.0)
Global vec_k:Vector =New Vector(0.0,0.0,0.0)
Global vec_v:Vector =New Vector(0.0,0.0,0.0)
' requires two absolute positional values
Function Pick:TEntity(ax:Float,ay:Float,az:Float,bx:Float,by:Float,bz:Float,radius:Float=0.0)
mat.LoadIdentity()
picked_ent=Null
picked_time=1.0
Local pick:Int =False
Local col_obj:CollisionObject = New CollisionObject()
Local line:Line = New Line(ax,ay,az,bx-ax,by-ay,bz-az)
'Local ray:Vector = New Vector((line.d.x-ax),(line.d.y-ay),(line.d.z-az)).Normalize()
Local ray:Vector = New Vector((line.d.x),(line.d.y),(line.d.z)).Normalize()
Local cen:Vector = New Vector(0,0,0)
''coll ray info setup for pick
Local col_info:CollisionInfo = New CollisionInfo()
col_info.dir = ray
col_info.coll_line = line
col_info.radius = radius
col_info.radii = New Vector(radius,radius,radius)
col_info.y_scale = 1.0
For Local ent:TEntity=Eachin ent_list
If ent.pick_mode=0 Or ent.Hidden()=True Then Continue
''early sphere rejection
If TMesh(ent)
''only do this for meshes with cull_radius
Local rad:Float
If ent.cull_radius <0 Then rad = -ent.cull_radius*ent.cull_radius + radius Else rad = radius+ent.cull_radius
'' rad * largest entity global scale
rad = rad*Max(Max(ent.gsx,ent.gsy),ent.gsz)
If rad<0 Then rad=-rad
cen.Update(ent.mat.grid[3][0] - ax, ent.mat.grid[3][1] - ay,-ent.mat.grid[3][2] - az)
If Not col_obj.RaySphereTest(ray,cen, rad) Then Continue
Endif
col_info.CollisionSetup(ent, ent.pick_mode, col_obj)
pick = col_info.CollisionDetect(col_obj)
If pick
picked_ent=ent
Exit ''do we need to run through the list? yes for multiple objects, but we don't have that capability yet
Endif
Next
If picked_ent<>Null
picked_x=col_obj.col_coords.x
picked_y=col_obj.col_coords.y
picked_z=col_obj.col_coords.z
picked_nx=col_obj.col_normal.x
picked_ny=col_obj.col_normal.y
picked_nz=col_obj.col_normal.z
picked_time=col_obj.col_time
'picked_ent=ent
If TMesh(picked_ent)<>Null
picked_surface=col_obj.surface '& $0000ffff
Else
picked_surface=-1
Endif
picked_triangle=col_obj.index
Endif
col_obj = Null
Return picked_ent
End
End