PeriDyno 1.0.0
Loading...
Searching...
No Matches
DragSurfaceInteraction.cu
Go to the documentation of this file.
1#include "DragSurfaceInteraction.h"
2
3#include "Primitive/Primitive3D.h"
4
5#include <thrust/sort.h>
6#include <iostream>
7#include <OrbitCamera.h>
8#define max_vel (10)
9namespace dyno
10{
11
12
13 template<typename TDataType>
14 DragSurfaceInteraction<TDataType>::DragSurfaceInteraction()
15 {
16 this->ray1 = TRay3D<Real>();
17 this->ray2 = TRay3D<Real>();
18 this->isPressed = false;
19 this->intersectionCenter.resize(1);
20 this->needInit = true;
21 }
22
23 template<typename TDataType>
24 void DragSurfaceInteraction<TDataType>::onEvent(PMouseEvent event)
25 {
26 if (this->needInit) {
27 this->restoreAttribute.assign(this->inAttribute()->getData());
28 needInit = false;
29 this->varCacheEvent()->setValue(true);
30 }
31
32 if (!event.altKeyPressed() && event.controlKeyPressed()) {
33 if (camera == nullptr)
34 {
35 this->camera = event.camera;
36 }
37
38 if (event.actionType == AT_PRESS)
39 {
40 this->camera = event.camera;
41 this->isPressed = true;
42 this->ray1.origin = event.ray.origin;
43 this->ray1.direction = event.ray.direction;
44 this->x1 = event.x;
45 this->y1 = event.y;
46
47 this->InteractionClick();
48 //printf("Mouse pressed: Origin: %f %f %f; Direction: %f %f %f \n", event.ray.origin.x, event.ray.origin.y, event.ray.origin.z, event.ray.direction.x, event.ray.direction.y, event.ray.direction.z);
49 }
50 else if (event.actionType == AT_RELEASE)
51 {
52 this->isPressed = false;
53 this->cancelVelocity();
54 this->inAttribute()->getData().assign(this->restoreAttribute);
55 this->intersectionCenter.reset();
56 //printf("Mouse released: Origin: %f %f %f; Direction: %f %f %f \n", event.ray.origin.x, event.ray.origin.y, event.ray.origin.z, event.ray.direction.x, event.ray.direction.y, event.ray.direction.z);
57
58 }
59 else //pressed while moving(drag action) or just moving
60 {
61
62 if (this->isPressed)
63 {
64 this->ray2.origin = event.ray.origin;
65 this->ray2.direction = event.ray.direction;
66 this->x2 = event.x;
67 this->y2 = event.y;
68 if (this->x2 == this->x1 && this->y2 == this->y1)
69 {
70 //change velocity to zero yet
71 this->cancelVelocity();
72 }
73 else
74 {
75 this->InteractionDrag();
76 //printf("Mouse repeated Draging: Origin: %f %f %f; Direction: %f %f %f \n", event.ray.origin.x, event.ray.origin.y, event.ray.origin.z, event.ray.direction.x, event.ray.direction.y, event.ray.direction.z);
77
78 }
79 //swap
80 this->ray1.origin = event.ray.origin;
81 this->ray1.direction = event.ray.direction;
82 this->x1 = event.x;
83 this->y1 = event.y;
84 }
85 }
86 }
87 }
88
89 __global__ void DS_SurfaceInitializeArray(
90 DArray<int> intersected)
91 {
92 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
93 if (pId >= intersected.size()) return;
94
95 intersected[pId] = 0;
96 }
97
98 template <typename Triangle, typename Real, typename Coord>
99 __global__ void DS_CalcIntersectedTrisRay(
100 DArray<Coord> points,
101 DArray<Triangle> triangles,
102 DArray<int> intersected,
103 DArray<int> unintersected,
104 DArray<Coord> interPoints,
105 TRay3D<Real> mouseray)
106 {
107 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
108 if (pId >= triangles.size()) return;
109
110 TTriangle3D<Real> t = TTriangle3D<Real>(points[triangles[pId][0]], points[triangles[pId][1]], points[triangles[pId][2]]);
111 int temp = 0;
112
113 TPoint3D<Real> p;
114 temp = mouseray.intersect(t, p);
115
116 if (temp == 1 || intersected[pId] == 1)
117 {
118 intersected[pId] = 1;
119 interPoints[pId] = p.origin;
120 }
121 else
122 {
123 intersected[pId] = 0;
124 interPoints[pId] = Vec3f(0);
125 }
126 unintersected[pId] = (intersected[pId] == 1 ? 0 : 1);
127 }
128
129 template <typename Real, typename Coord>
130 __global__ void DS_CalcTrisDistance(
131 DArray<Coord> interPoints,
132 DArray<Real> trisDistance,
133 DArray<int> intersected,
134 TRay3D<Real> mouseray)
135 {
136 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
137 if (pId >= interPoints.size()) return;
138 if (intersected[pId] !=0)
139 {
140 TPoint3D<Real> origin = TPoint3D<Real>(mouseray.origin);
141 TPoint3D<Real> p = TPoint3D<Real>(interPoints[pId]);
142 trisDistance[pId] = origin.distance(TPoint3D<Real>(p));
143 }
144 else
145 {
146 trisDistance[pId] = 3.4E38;
147 }
148 }
149
150 __global__ void DS_CalcTrisNearest(
151 int min_index,
152 DArray<int> intersected,
153 DArray<int> unintersected)
154 {
155 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
156 if (pId >= intersected.size()) return;
157
158 if (intersected[pId] == 1)
159 {
160 if (pId != min_index)
161 {
162 intersected[pId] = 0;
163 unintersected[pId] = 1;
164 }
165 }
166 }
167
168 template <typename Triangle, typename Coord, typename Real>
169 __global__ void DS_FindNearbyTris(
170 DArray<Coord> points,
171 DArray<Triangle> triangles,
172 DArray<Coord> interPoints,
173 DArray<int> intersected,
174 DArray<int> unintersected,
175 DArray<Coord> center,
176 int min_index,
177 Real intersectionRadius
178 )
179 {
180 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
181 if (pId >= intersected.size()) return;
182
183
184 TPoint3D<Real> p = TPoint3D<Real>(interPoints[min_index]);
185 TSegment3D<Real> s1 = TSegment3D<Real>(points[triangles[pId][0]], points[triangles[pId][1]]);
186 TSegment3D<Real> s2 = TSegment3D<Real>(points[triangles[pId][1]], points[triangles[pId][2]]);
187 TSegment3D<Real> s3 = TSegment3D<Real>(points[triangles[pId][2]], points[triangles[pId][0]]);
188 if (pId == min_index)
189 center[0] = interPoints[min_index];
190
191 Real d1 = p.distance(s1);
192 Real d2 = p.distance(s2);
193 Real d3 = p.distance(s3);
194 if (!(d1 > intersectionRadius && d2 > intersectionRadius && d3 > intersectionRadius) || intersected[pId]==1)
195 {
196 intersected[pId] = 1;
197 unintersected[pId] = 0;
198 }
199 else
200 {
201 intersected[pId] = 0;
202 unintersected[pId] = 1;
203 }
204 }
205
206
207 __global__ void DS_AssignOutTriangles(
208 DArray<int> intersected_triangles,
209 DArray<int> intersected,
210 DArray<int> intersected_o)
211 {
212 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
213 if (pId >= intersected_o.size()) return;
214
215 if (intersected_o[pId] == 1)
216 {
217 intersected_triangles[intersected[pId]] = pId;
218 }
219 }
220
221 template<typename TDataType>
222 void DragSurfaceInteraction<TDataType>::calcSurfaceInteractClick()
223
224 {
225
226 auto& initialTriangleSet = this->inInitialTriangleSet()->getData();
227 auto& points = initialTriangleSet.getPoints();
228 auto& triangles = initialTriangleSet.getTriangles();
229
230 DArray<int> intersected;
231 intersected.resize(triangles.size());
232 cuExecute(triangles.size(),
233 DS_SurfaceInitializeArray,
234 intersected
235 );
236
237 DArray<int> unintersected;
238 unintersected.resize(triangles.size());
239
240 DArray<Coord> interPoints;
241 interPoints.resize(triangles.size());
242
243 cuExecute(triangles.size(),
244 DS_CalcIntersectedTrisRay,
245 points,
246 triangles,
247 intersected,
248 unintersected,
249 interPoints,
250 this->ray1
251 );
252
253
254 DArray<Real> trisDistance;
255 trisDistance.resize(interPoints.size());
256
257 cuExecute(interPoints.size(),
258 DS_CalcTrisDistance,
259 interPoints,
260 trisDistance,
261 intersected,
262 this->ray1
263 );
264
265 int min_index = thrust::min_element(thrust::device, trisDistance.begin(), trisDistance.begin() + trisDistance.size()) - trisDistance.begin();
266 this->intersectionCenterIndex = min_index;
267 cuExecute(intersected.size(),
268 DS_CalcTrisNearest,
269 min_index,
270 intersected,
271 unintersected
272 );
273
274 cuExecute(triangles.size(),
275 DS_FindNearbyTris,
276 points,
277 triangles,
278 interPoints,
279 intersected,
280 unintersected,
281 this->intersectionCenter,
282 min_index,
283 this->varInterationRadius()->getData()
284 );
285
286
287 this->triIntersectedIndex.assign(intersected);
288
289 DArray<int> intersected_o;
290 intersected_o.assign(intersected);
291
292 int intersected_size = thrust::reduce(thrust::device, intersected.begin(), intersected.begin() + intersected.size(), (int)0, thrust::plus<int>());
293 thrust::exclusive_scan(thrust::device, intersected.begin(), intersected.begin() + intersected.size(), intersected.begin());
294
295 this->intersected_triangles.resize(intersected_size);
296
297 cuExecute(triangles.size(),
298 DS_AssignOutTriangles,
299 this->intersected_triangles,
300 intersected,
301 intersected_o
302 );
303
304 intersected_o.clear();
305
306 }
307
308 template <typename Real, typename Coord>
309 __global__ void DS_SetFollowed(
310 DArray<Attribute> att,
311 DArray<Attribute> restore_att,
312 DArray<Coord> Velocity,
313 DArray<Coord> Position,
314 Real timestep) {
315 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
316 if (pId >= att.size()) return;
317
318 if (!restore_att[pId].isFixed() && att[pId].isFixed()) { //set fixed by drag
319 Position[pId] += Velocity[pId] * timestep;
320 }
321
322 }
323
324 template<typename TDataType>
325 void DragSurfaceInteraction<TDataType>::cancelVelocity() {
326 CArray<Coord> movement_c;
327 movement_c.resize(1);
328 movement_c[0] = Coord(0);
329 DArray<Coord> movement;
330 movement.resize(1);
331 movement.assign(movement_c);
332
333 auto& initialTriangleSet = this->inInitialTriangleSet()->getData();
334 auto& triangles = initialTriangleSet.getTriangles();
335
336 cuExecute(this->intersected_triangles.size(),
337 DS_SetupVelocity,
338 this->inVelocity()->getData(),
339 movement,
340 triangles,
341 this->intersected_triangles,
342 this->inTimeStep()->getData()
343 );
344 movement_c.clear();
345 movement.clear();
346 }
347
348 template <typename Triangle, typename Real, typename Coord>
349 __global__ void DS_SetupVelocity(
350 DArray<Coord> Velocity,
351 DArray<Coord> movement,
352 DArray<Triangle> triangles,
353 DArray<int> intersectionList,
354 Real timestep)
355 {
356 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
357 if (pId >= intersectionList.size()) return;
358
359 Triangle tri = triangles[intersectionList[pId]];
360 Coord velocity_candidate = movement[0] / timestep;
361 if (velocity_candidate.norm() >= max_vel)
362 velocity_candidate /= (velocity_candidate.norm() / max_vel);
363
364 for (int index_tri = 0; index_tri < 3; ++index_tri)
365 {
366 Velocity[tri[index_tri]] = velocity_candidate;
367 }
368
369 }
370
371 template<typename TDataType>
372 void DragSurfaceInteraction<TDataType>::calcSurfaceInteractDrag()
373
374 {
375
376 TRay3D<Real> ray1 = this->ray1;
377 TRay3D<Real> ray2 = this->ray2;
378
379 TRay3D<Real> ray_o = this->camera->castRayInWorldSpace((float)0.0, (float)0.0);
380
381 float height = this->camera->viewportHeight()/2.0;
382 float width = this->camera->viewportWidth()/2.0;
383 TRay3D<Real> ray_horizon = this->camera->castRayInWorldSpace(width, (float)0.0);
384 TRay3D<Real> ray_vertical = this->camera->castRayInWorldSpace((float)0.0, height);
385
386 //printf("(x1,y1) = %f,%f (x2,y2) = %f,%f\n", x1, y1, x2, y2);
387 auto ray_h = ray_o.origin - ray_horizon.origin;
388 auto ray_v = ray_o.origin - ray_vertical.origin;
389 auto N_plane = ray_h.cross(ray_v);
390
391 if (N_plane.norm() ==0.0) //error
392 return;
393
394 N_plane /= N_plane.norm();
395 CArray<Coord> center; //this is a copy of intersectionCenter
396 CArray<Coord> movement_c; // this is a copy used to calc velocity
397 center.resize(1);
398 center.assign(this->intersectionCenter);
399 movement_c.resize(1);
400 movement_c.assign(this->intersectionCenter);
401
402 TPlane3D<Real> focal_plane = TPlane3D<Real>(center[0], N_plane);
403 TPoint3D<Real> p;
404 int temp = ray2.intersect(focal_plane, p);
405 movement_c[0] = p.origin-center[0];
406
407 Real dt = (Real)this->inTimeStep()->getData();
408 Coord velocity_candidate = movement_c[0] / dt;
409 if (velocity_candidate.norm() >= max_vel)
410 velocity_candidate /= (velocity_candidate.norm() / max_vel);
411
412 center[0] += velocity_candidate * dt;
413 this->intersectionCenter.assign(center);
414
415 DArray<Coord> movement;
416 movement.resize(1);
417 movement.assign(movement_c);
418 auto& initialTriangleSet = this->inInitialTriangleSet()->getData();
419 auto& triangles = initialTriangleSet.getTriangles();
420
421 cuExecute(this->intersected_triangles.size(),
422 DS_SetupVelocity,
423 this->inVelocity()->getData(),
424 movement,
425 triangles,
426 this->intersected_triangles,
427 this->inTimeStep()->getData()
428 );
429 cuSynchronize();
430
431 cuExecute(this->inPosition()->getData().size(),
432 DS_SetFollowed,
433 this->inAttribute()->getData(),
434 this->restoreAttribute,
435 this->inVelocity()->getData(),
436 this->inPosition()->getData(),
437 this->inTimeStep()->getData()
438 );
439
440 movement.clear();
441 movement_c.clear();
442 center.clear();
443
444 //printf("==============================end intersection================================\n");
445 }
446
447 template <typename Triangle>
448 __global__ void DS_FixedPoint(
449 DArray<Triangle> triangles,
450 DArray<int> intersected_tri,
451 DArray<Attribute> inAtt) {
452
453 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
454 if (tId >= intersected_tri.size()) return;
455
456 int t_intersected_index = intersected_tri[tId];
457 const Triangle& t = triangles[t_intersected_index];
458 for (int index_t = 0; index_t < 3; ++index_t) {
459 Attribute& att = inAtt[t[index_t]];
460 att.setFixed();
461 }
462
463 }
464
465 template<typename TDataType>
466 void DragSurfaceInteraction<TDataType>::setTriFixed() {
467 auto& TriSet = this->inInitialTriangleSet()->getData();
468 auto& triangles = TriSet.getTriangles();
469 int tNum = triangles.size();
470 cuExecute(tNum,
471 DS_FixedPoint,
472 triangles,
473 this->intersected_triangles,
474 this->inAttribute()->getData()
475 );
476 }
477
478
479 template<typename TDataType>
480 void DragSurfaceInteraction<TDataType>::InteractionClick()
481 {
482
483 calcSurfaceInteractClick();
484 this->setTriFixed();
485
486 }
487
488 template<typename TDataType>
489 void DragSurfaceInteraction<TDataType>::InteractionDrag()
490 {
491
492 calcSurfaceInteractDrag();
493
494 }
495
496 DEFINE_CLASS(DragSurfaceInteraction);
497}