summaryrefslogtreecommitdiff
path: root/thirdparty/embree/kernels/common/point_query.h
blob: 7d55c91fff8271354471183a8506e5e2a7621717 (plain)
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
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "default.h"

namespace embree
{
  /* Point query structure for closest point query */
  template<int K>
  struct RTC_ALIGN(16) PointQueryK 
  {
    /* Default construction does nothing */
    __forceinline PointQueryK() {}

    /* Constructs a ray from origin, direction, and ray segment. Near
     * has to be smaller than far */
    __forceinline PointQueryK(const Vec3vf<K>& p, const vfloat<K>& radius = inf, const vfloat<K>& time = zero)
      : p(p), time(time), radius(radius) {}

    /* Returns the size of the ray */
    static __forceinline size_t size() { return K; }

    /* Calculates if this is a valid ray that does not cause issues during traversal */
    __forceinline vbool<K> valid() const
    {
      const vbool<K> vx = (abs(p.x) <= vfloat<K>(FLT_LARGE));
      const vbool<K> vy = (abs(p.y) <= vfloat<K>(FLT_LARGE));
      const vbool<K> vz = (abs(p.z) <= vfloat<K>(FLT_LARGE));
      const vbool<K> vn = radius >= vfloat<K>(0);
      const vbool<K> vf = abs(time) < vfloat<K>(inf);
      return vx & vy & vz & vn & vf;
    }

    __forceinline void get(PointQueryK<1>* ray) const;
    __forceinline void get(size_t i, PointQueryK<1>& ray) const;
    __forceinline void set(const PointQueryK<1>* ray);
    __forceinline void set(size_t i, const PointQueryK<1>& ray);

    Vec3vf<K> p;      // location of the query point
    vfloat<K> time;   // time for motion blur
    vfloat<K> radius; // radius for the point query
  };
  
  /* Specialization for a single point query */
  template<>
  struct RTC_ALIGN(16) PointQueryK<1>
  {
    /* Default construction does nothing */
    __forceinline PointQueryK() {}

    /* Constructs a ray from origin, direction, and ray segment. Near
     *  has to be smaller than far */
    __forceinline PointQueryK(const Vec3fa& p, float radius = inf, float time = zero)
      : p(p), time(time), radius(radius) {}

    /* Calculates if this is a valid ray that does not cause issues during traversal */
    __forceinline bool valid() const {
      return all(le_mask(abs(Vec3fa(p)), Vec3fa(FLT_LARGE)) & le_mask(Vec3fa(0.f), Vec3fa(radius))) && abs(time) < float(inf);
    }

    Vec3f p;  
    float time;
    float radius;
  };
  
  /* Converts point query packet to single point query */
  template<int K>
  __forceinline void PointQueryK<K>::get(PointQueryK<1>* query) const
  {
    for (size_t i = 0; i < K; i++) // FIXME: use SIMD transpose
    {
      query[i].p.x    = p.x[i]; 
      query[i].p.y    = p.y[i]; 
      query[i].p.z    = p.z[i];
      query[i].time   = time[i];
      query[i].radius = radius[i]; 
    }
  }

  /* Extracts a single point query out of a point query packet*/
  template<int K>
  __forceinline void PointQueryK<K>::get(size_t i, PointQueryK<1>& query) const
  {
    query.p.x    = p.x[i]; 
    query.p.y    = p.y[i]; 
    query.p.z    = p.z[i];
    query.radius = radius[i];  
    query.time   = time[i];  
  }

  /* Converts single point query to point query packet */
  template<int K>
  __forceinline void PointQueryK<K>::set(const PointQueryK<1>* query)
  {
    for (size_t i = 0; i < K; i++)
    {
      p.x[i]    = query[i].p.x;
      p.y[i]    = query[i].p.y;
      p.z[i]    = query[i].p.z;
      radius[i] = query[i].radius; 
      time[i]   = query[i].time; 
    }
  }

  /* inserts a single point query into a point query packet element */
  template<int K>
  __forceinline void PointQueryK<K>::set(size_t i, const PointQueryK<1>& query)
  {
    p.x[i]    = query.p.x;
    p.y[i]    = query.p.y;
    p.z[i]    = query.p.z;
    radius[i] = query.radius; 
    time[i]   = query.time; 
  }

  /* Shortcuts */
  typedef PointQueryK<1>  PointQuery;
  typedef PointQueryK<4>  PointQuery4;
  typedef PointQueryK<8>  PointQuery8;
  typedef PointQueryK<16> PointQuery16;
  struct PointQueryN;

  /* Outputs point query to stream */
  template<int K>
  __forceinline embree_ostream operator <<(embree_ostream cout, const PointQueryK<K>& query)
  {
    cout << "{ " << embree_endl
        << "  p = "    << query.p      << embree_endl
        << "  r = "    << query.radius << embree_endl
        << "  time = " << query.time   << embree_endl
        << "}";
    return cout;
  }
}