ParticleAPI 3.0.0 Performant particle system API in C++ for interactive graphics

pVec.h
Go to the documentation of this file.
1/// PVec.h - yet another 3D vector class
2///
3/// Copyright 1997-2007, 2022 by David K. McAllister
4///
5/// A simple 3D float vector class for internal use by the particle systems.
6
7#ifndef pvec_h
8#define pvec_h
9
10#include <cmath>
11#include <iostream>
12
13#ifndef M_PI
14#define M_PI 3.1415926535897932384626433f
15#endif
16
17#ifdef WIN32
18#define PINLINE __forceinline
19#else
20#define PINLINE inline
21#endif
22
23namespace PAPI {
24 const float P_SQRT2PI = 2.506628274631000502415765284811045253006f;
25 const float P_ONEOVERSQRT2PI = (1.f / P_SQRT2PI);
26
27 PINLINE float fsqr(float f) { return f * f; }
28
29#ifdef unix
30 PINLINE float pRandf() { return drand48(); }
31 PINLINE void pSRandf(int x) { srand48(x); }
32#else
33 const float P_ONEOVER_RAND_MAX = (1.0f / ((float)RAND_MAX));
34 PINLINE float pRandf() { return ((float)rand()) * P_ONEOVER_RAND_MAX; }
35 PINLINE void pSRandf(int x) { srand(x); }
36#endif
37
38 PINLINE bool pSameSign(const float& a, const float& b) { return a * b >= 0.0f; }
39
40/// Return a random number with a normal distribution.
41 PINLINE float pNRandf(float sigma = 1.0f)
42{
43 float x, y, r2;
44 do {
45 x = pRandf() * 2.0f - 1.0f;
46 y = pRandf() * 2.0f - 1.0f;
47 r2 = x * x + y * y;
48 } while (r2 > 1.0f || r2 == 0.0f);
49
50 float m = sqrtf(-2.0f * logf(r2) / r2);
51
52 float px = x * m * sigma;
53 // float py = y*m*sigma;
54
55 return px;
56}
57
58/// A single-precision floating point three-vector.
59///
60/// This class is used for packaging three floats for the application to pass into the API.
61///
62/// This is also the class used internally to do vector math.
63 class pVec {
64 float vx, vy, vz;
65
66public:
67 PINLINE pVec(float ax, float ay, float az) : vx(ax), vy(ay), vz(az) {}
68 PINLINE pVec(float a) : vx(a), vy(a), vz(a) {}
69 PINLINE pVec() = default;
70 PINLINE pVec(float* v) : vx(v[0]), vy(v[1]), vz(v[2]) {}
71
72 const float& x() const { return vx; }
73 const float& y() const { return vy; }
74 const float& z() const { return vz; }
75
76 float& x() { return vx; }
77 float& y() { return vy; }
78 float& z() { return vz; }
79
80 PINLINE float length() const { return sqrtf(vx * vx + vy * vy + vz * vz); }
81
82 PINLINE float lenSqr() const { return (vx * vx + vy * vy + vz * vz); }
83
84 PINLINE float normalize(const float toLen = 1.f)
85 {
86 float onel = toLen / sqrtf(vx * vx + vy * vy + vz * vz);
87 vx *= onel;
88 vy *= onel;
89 vz *= onel;
90
91 return onel;
92 }
93
94 // Dot product
95 friend PINLINE float dot(const pVec& a, const pVec& b) { return b.x() * a.x() + b.y() * a.y() + b.z() * a.z(); }
96
97 // Scalar multiply
98 PINLINE pVec operator*(const float s) const { return pVec(vx * s, vy * s, vz * s); }
99
100 PINLINE pVec operator/(const float s) const
101 {
102 float invs = 1.0f / s;
103 return pVec(vx * invs, vy * invs, vz * invs);
104 }
105
106 PINLINE pVec operator+(const pVec& a) const { return pVec(vx + a.x(), vy + a.y(), vz + a.z()); }
107
108 PINLINE pVec operator-(const pVec& a) const { return pVec(vx - a.x(), vy - a.y(), vz - a.z()); }
109
110 PINLINE bool operator==(const pVec& a) const { return vx == a.x() && vy == a.y() && vz == a.z(); }
111
112 PINLINE pVec operator-()
113 {
114 vx = -vx;
115 vy = -vy;
116 vz = -vz;
117 return *this;
118 }
119
120 PINLINE pVec& operator+=(const pVec& a)
121 {
122 vx += a.x();
123 vy += a.y();
124 vz += a.z();
125 return *this;
126 }
127
128 PINLINE pVec& operator-=(const pVec& a)
129 {
130 vx -= a.x();
131 vy -= a.y();
132 vz -= a.z();
133 return *this;
134 }
135
136 PINLINE pVec& operator*=(const float a)
137 {
138 vx *= a;
139 vy *= a;
140 vz *= a;
141 return *this;
142 }
143
144 PINLINE pVec& operator/=(const float a)
145 {
146 float b = 1.0f / a;
147 vx *= b;
148 vy *= b;
149 vz *= b;
150 return *this;
151 }
152
153 bool isNan() { return std::isnan(x()) || std::isnan(y()) || std::isnan(z()); }
154
155 // Component-wise absolute value
156 friend PINLINE pVec Abs(const pVec& a) { return pVec(fabs(a.x()), fabs(a.y()), fabs(a.z())); }
157
158 // Component-wise multiply
159 friend PINLINE pVec CompMult(const pVec& a, const pVec& b) { return pVec(b.x() * a.x(), b.y() * a.y(), b.z() * a.z()); }
160
161 friend PINLINE pVec Cross(const pVec& a, const pVec& b)
162 {
163 return pVec(a.y() * b.z() - a.z() * b.y(), a.z() * b.x() - a.x() * b.z(), a.x() * b.y() - a.y() * b.x());
164 }
165
166 friend PINLINE std::ostream& operator<<(std::ostream& os, const pVec& v)
167 {
168 os << &v << '[' << v.x() << ", " << v.y() << ", " << v.z() << ']';
169
170 return os;
171 }
172};
173
174// To offset [0 .. 1] vectors to [-.5 .. .5]
175static pVec vHalf(0.5, 0.5, 0.5);
176
177 PINLINE pVec pRandVec() { return pVec(pRandf(), pRandf(), pRandf()); }
178
179 PINLINE pVec pNRandVec(float sigma)
180{
181 float x, y, r2;
182 do {
183 x = pRandf() * 2.0f - 1.0f;
184 y = pRandf() * 2.0f - 1.0f;
185 r2 = x * x + y * y;
186 } while (r2 > 1.0f || r2 == 0.0f);
187
188 float m = sqrtf(-2.0f * logf(r2) / r2);
189
190 float px = x * m * sigma;
191 float py = y * m * sigma;
192 return pVec(px, py, pNRandf(sigma));
193}
194}; // namespace PAPI
195
196#endif
PAPI::pVec
A single-precision floating point three-vector.
Definition: pVec.h:63
PAPI::pVec::Abs
friend pVec Abs(const pVec &a)
Definition: pVec.h:156
PAPI::pVec::CompMult
friend pVec CompMult(const pVec &a, const pVec &b)
Definition: pVec.h:159
PAPI::pVec::normalize
float normalize(const float toLen=1.f)
Definition: pVec.h:84
PAPI::pVec::pVec
pVec(float ax, float ay, float az)
Definition: pVec.h:67
PAPI::pVec::operator+
pVec operator+(const pVec &a) const
Definition: pVec.h:106
PAPI::pVec::operator*
pVec operator*(const float s) const
Definition: pVec.h:98
PAPI::pVec::isNan
bool isNan()
Definition: pVec.h:153
PAPI::pVec::dot
friend float dot(const pVec &a, const pVec &b)
Definition: pVec.h:95
PAPI::pVec::x
const float & x() const
Definition: pVec.h:72
PAPI::pVec::y
float & y()
Definition: pVec.h:77
PAPI::pVec::operator-
pVec operator-(const pVec &a) const
Definition: pVec.h:108
PAPI::pVec::pVec
pVec()=default
PAPI::pVec::operator/=
pVec & operator/=(const float a)
Definition: pVec.h:144
PAPI::pVec::operator==
bool operator==(const pVec &a) const
Definition: pVec.h:110
PAPI::pVec::operator*=
pVec & operator*=(const float a)
Definition: pVec.h:136
PAPI::pVec::operator-
pVec operator-()
Definition: pVec.h:112
PAPI::pVec::operator-=
pVec & operator-=(const pVec &a)
Definition: pVec.h:128
PAPI::pVec::x
float & x()
Definition: pVec.h:76
PAPI::pVec::length
float length() const
Definition: pVec.h:80
PAPI::pVec::y
const float & y() const
Definition: pVec.h:73
PAPI::pVec::lenSqr
float lenSqr() const
Definition: pVec.h:82
PAPI::pVec::operator+=
pVec & operator+=(const pVec &a)
Definition: pVec.h:120
PAPI::pVec::operator/
pVec operator/(const float s) const
Definition: pVec.h:100
PAPI::pVec::pVec
pVec(float a)
Definition: pVec.h:68
PAPI::pVec::z
const float & z() const
Definition: pVec.h:74
PAPI::pVec::pVec
pVec(float *v)
Definition: pVec.h:70
PAPI::pVec::z
float & z()
Definition: pVec.h:78
PAPI::pVec::Cross
friend pVec Cross(const pVec &a, const pVec &b)
Definition: pVec.h:161
PAPI
PAPIClasses.h.
Definition: pAPIContext.h:16
PAPI::pRandf
float pRandf()
Definition: pVec.h:34
PAPI::pNRandVec
pVec pNRandVec(float sigma)
Definition: pVec.h:179
PAPI::pSameSign
bool pSameSign(const float &a, const float &b)
Definition: pVec.h:38
PAPI::P_ONEOVER_RAND_MAX
const float P_ONEOVER_RAND_MAX
Definition: pVec.h:33
PAPI::P_ONEOVERSQRT2PI
const float P_ONEOVERSQRT2PI
Definition: pVec.h:25
PAPI::P_SQRT2PI
const float P_SQRT2PI
Definition: pVec.h:24
PAPI::pSRandf
void pSRandf(int x)
Definition: pVec.h:35
PAPI::fsqr
float fsqr(float f)
Definition: pVec.h:27
PAPI::pRandVec
pVec pRandVec()
Definition: pVec.h:177
PAPI::pNRandf
float pNRandf(float sigma=1.0f)
Return a random number with a normal distribution.
Definition: pVec.h:41
PINLINE
#define PINLINE
Definition: pVec.h:20