1#include "DragSurfaceInteraction.h"
3#include "Primitive/Primitive3D.h"
5#include <thrust/sort.h>
7#include <OrbitCamera.h>
13 template<typename TDataType>
14 DragSurfaceInteraction<TDataType>::DragSurfaceInteraction()
16 this->ray1 = TRay3D<Real>();
17 this->ray2 = TRay3D<Real>();
18 this->isPressed = false;
19 this->intersectionCenter.resize(1);
20 this->needInit = true;
23 template<typename TDataType>
24 void DragSurfaceInteraction<TDataType>::onEvent(PMouseEvent event)
27 this->restoreAttribute.assign(this->inAttribute()->getData());
29 this->varCacheEvent()->setValue(true);
32 if (!event.altKeyPressed() && event.controlKeyPressed()) {
33 if (camera == nullptr)
35 this->camera = event.camera;
38 if (event.actionType == AT_PRESS)
40 this->camera = event.camera;
41 this->isPressed = true;
42 this->ray1.origin = event.ray.origin;
43 this->ray1.direction = event.ray.direction;
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);
50 else if (event.actionType == AT_RELEASE)
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);
59 else //pressed while moving(drag action) or just moving
64 this->ray2.origin = event.ray.origin;
65 this->ray2.direction = event.ray.direction;
68 if (this->x2 == this->x1 && this->y2 == this->y1)
70 //change velocity to zero yet
71 this->cancelVelocity();
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);
80 this->ray1.origin = event.ray.origin;
81 this->ray1.direction = event.ray.direction;
89 __global__ void DS_SurfaceInitializeArray(
90 DArray<int> intersected)
92 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
93 if (pId >= intersected.size()) return;
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)
107 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
108 if (pId >= triangles.size()) return;
110 TTriangle3D<Real> t = TTriangle3D<Real>(points[triangles[pId][0]], points[triangles[pId][1]], points[triangles[pId][2]]);
114 temp = mouseray.intersect(t, p);
116 if (temp == 1 || intersected[pId] == 1)
118 intersected[pId] = 1;
119 interPoints[pId] = p.origin;
123 intersected[pId] = 0;
124 interPoints[pId] = Vec3f(0);
126 unintersected[pId] = (intersected[pId] == 1 ? 0 : 1);
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)
136 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
137 if (pId >= interPoints.size()) return;
138 if (intersected[pId] !=0)
140 TPoint3D<Real> origin = TPoint3D<Real>(mouseray.origin);
141 TPoint3D<Real> p = TPoint3D<Real>(interPoints[pId]);
142 trisDistance[pId] = origin.distance(TPoint3D<Real>(p));
146 trisDistance[pId] = 3.4E38;
150 __global__ void DS_CalcTrisNearest(
152 DArray<int> intersected,
153 DArray<int> unintersected)
155 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
156 if (pId >= intersected.size()) return;
158 if (intersected[pId] == 1)
160 if (pId != min_index)
162 intersected[pId] = 0;
163 unintersected[pId] = 1;
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,
177 Real intersectionRadius
180 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
181 if (pId >= intersected.size()) return;
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];
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)
196 intersected[pId] = 1;
197 unintersected[pId] = 0;
201 intersected[pId] = 0;
202 unintersected[pId] = 1;
207 __global__ void DS_AssignOutTriangles(
208 DArray<int> intersected_triangles,
209 DArray<int> intersected,
210 DArray<int> intersected_o)
212 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
213 if (pId >= intersected_o.size()) return;
215 if (intersected_o[pId] == 1)
217 intersected_triangles[intersected[pId]] = pId;
221 template<typename TDataType>
222 void DragSurfaceInteraction<TDataType>::calcSurfaceInteractClick()
226 auto& initialTriangleSet = this->inInitialTriangleSet()->getData();
227 auto& points = initialTriangleSet.getPoints();
228 auto& triangles = initialTriangleSet.getTriangles();
230 DArray<int> intersected;
231 intersected.resize(triangles.size());
232 cuExecute(triangles.size(),
233 DS_SurfaceInitializeArray,
237 DArray<int> unintersected;
238 unintersected.resize(triangles.size());
240 DArray<Coord> interPoints;
241 interPoints.resize(triangles.size());
243 cuExecute(triangles.size(),
244 DS_CalcIntersectedTrisRay,
254 DArray<Real> trisDistance;
255 trisDistance.resize(interPoints.size());
257 cuExecute(interPoints.size(),
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(),
274 cuExecute(triangles.size(),
281 this->intersectionCenter,
283 this->varInterationRadius()->getData()
287 this->triIntersectedIndex.assign(intersected);
289 DArray<int> intersected_o;
290 intersected_o.assign(intersected);
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());
295 this->intersected_triangles.resize(intersected_size);
297 cuExecute(triangles.size(),
298 DS_AssignOutTriangles,
299 this->intersected_triangles,
304 intersected_o.clear();
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,
315 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
316 if (pId >= att.size()) return;
318 if (!restore_att[pId].isFixed() && att[pId].isFixed()) { //set fixed by drag
319 Position[pId] += Velocity[pId] * timestep;
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;
331 movement.assign(movement_c);
333 auto& initialTriangleSet = this->inInitialTriangleSet()->getData();
334 auto& triangles = initialTriangleSet.getTriangles();
336 cuExecute(this->intersected_triangles.size(),
338 this->inVelocity()->getData(),
341 this->intersected_triangles,
342 this->inTimeStep()->getData()
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,
356 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
357 if (pId >= intersectionList.size()) return;
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);
364 for (int index_tri = 0; index_tri < 3; ++index_tri)
366 Velocity[tri[index_tri]] = velocity_candidate;
371 template<typename TDataType>
372 void DragSurfaceInteraction<TDataType>::calcSurfaceInteractDrag()
376 TRay3D<Real> ray1 = this->ray1;
377 TRay3D<Real> ray2 = this->ray2;
379 TRay3D<Real> ray_o = this->camera->castRayInWorldSpace((float)0.0, (float)0.0);
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);
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);
391 if (N_plane.norm() ==0.0) //error
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
398 center.assign(this->intersectionCenter);
399 movement_c.resize(1);
400 movement_c.assign(this->intersectionCenter);
402 TPlane3D<Real> focal_plane = TPlane3D<Real>(center[0], N_plane);
404 int temp = ray2.intersect(focal_plane, p);
405 movement_c[0] = p.origin-center[0];
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);
412 center[0] += velocity_candidate * dt;
413 this->intersectionCenter.assign(center);
415 DArray<Coord> movement;
417 movement.assign(movement_c);
418 auto& initialTriangleSet = this->inInitialTriangleSet()->getData();
419 auto& triangles = initialTriangleSet.getTriangles();
421 cuExecute(this->intersected_triangles.size(),
423 this->inVelocity()->getData(),
426 this->intersected_triangles,
427 this->inTimeStep()->getData()
431 cuExecute(this->inPosition()->getData().size(),
433 this->inAttribute()->getData(),
434 this->restoreAttribute,
435 this->inVelocity()->getData(),
436 this->inPosition()->getData(),
437 this->inTimeStep()->getData()
444 //printf("==============================end intersection================================\n");
447 template <typename Triangle>
448 __global__ void DS_FixedPoint(
449 DArray<Triangle> triangles,
450 DArray<int> intersected_tri,
451 DArray<Attribute> inAtt) {
453 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
454 if (tId >= intersected_tri.size()) return;
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]];
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();
473 this->intersected_triangles,
474 this->inAttribute()->getData()
479 template<typename TDataType>
480 void DragSurfaceInteraction<TDataType>::InteractionClick()
483 calcSurfaceInteractClick();
488 template<typename TDataType>
489 void DragSurfaceInteraction<TDataType>::InteractionDrag()
492 calcSurfaceInteractDrag();
496 DEFINE_CLASS(DragSurfaceInteraction);