Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
Fadecandy
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
scanlime
Fadecandy
Commits
c5aafb0e
Commit
c5aafb0e
authored
11 years ago
by
Micah Elizabeth Scott
Browse files
Options
Downloads
Patches
Plain Diff
KD-tree particle index
parent
5cd09157
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
examples/cpp/lib/particle.h
+124
-7
124 additions, 7 deletions
examples/cpp/lib/particle.h
with
124 additions
and
7 deletions
examples/cpp/lib/particle.h
+
124
−
7
View file @
c5aafb0e
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#pragma once
#pragma once
#include
"effect.h"
#include
"effect.h"
#include
"nanoflann.h"
// Tiny KD-tree library
class
ParticleEffect
:
public
Effect
{
class
ParticleEffect
:
public
Effect
{
...
@@ -43,14 +44,39 @@ public:
...
@@ -43,14 +44,39 @@ public:
float
intensity
;
float
intensity
;
};
};
ParticleEffect
();
virtual
void
beginFrame
(
const
FrameInfo
&
f
);
virtual
void
calculatePixel
(
Vec3
&
rgb
,
const
PixelInfo
&
p
);
virtual
void
calculatePixel
(
Vec3
&
rgb
,
const
PixelInfo
&
p
);
virtual
void
debug
(
const
DebugInfo
&
d
);
protected
:
protected
:
/*
/*
* List of appearances for particles we're drawing. Calculate this in beginFrame(),
* List of appearances for particles we're drawing. Calculate this in beginFrame(),
* or keep it persistent across frames and update the parts you're changing.
* or keep it persistent across frames and update the parts you're changing.
*/
*/
std
::
vector
<
ParticleAppearance
>
appearance
;
typedef
std
::
vector
<
ParticleAppearance
>
AppearanceVector
;
AppearanceVector
appearance
;
/*
* KD-tree as a spatial index for finding particles quickly by location.
* This index is rebuilt each frame during ParticleEffect::buildFrame().
* The ParticleEffect itself uses this index for calculating pixel values,
* but subclasses may also want to use it for phyiscs or interaction.
*/
typedef
nanoflann
::
KDTreeSingleIndexAdaptor
<
nanoflann
::
L2_Simple_Adaptor
<
Real
,
ParticleEffect
>
,
ParticleEffect
,
3
>
IndexTree
;
struct
Index
{
Index
(
ParticleEffect
&
e
);
Vec3
aabbMin
;
Vec3
aabbMax
;
float
radiusMax
;
IndexTree
tree
;
}
index
;
/*
/*
* Kernel function; determines particle shape
* Kernel function; determines particle shape
...
@@ -65,6 +91,45 @@ protected:
...
@@ -65,6 +91,45 @@ protected:
// First derivative of kernel()
// First derivative of kernel()
float
kernelDerivative
(
float
q
);
float
kernelDerivative
(
float
q
);
private
:
// Debug statistics
unsigned
particlesPerPixelNumerator
;
unsigned
particlesPerPixelDenominator
;
public
:
// Implementation glue for our KD-tree index
inline
size_t
kdtree_get_point_count
()
const
{
return
appearance
.
size
();
}
inline
Real
kdtree_distance
(
const
Real
*
p1
,
const
size_t
idx_p2
,
size_t
size
)
const
{
const
ParticleAppearance
&
a
=
appearance
[
idx_p2
];
Real
d0
=
p1
[
0
]
-
a
.
point
[
0
];
Real
d1
=
p1
[
1
]
-
a
.
point
[
1
];
Real
d2
=
p1
[
2
]
-
a
.
point
[
2
];
return
sq
(
d0
)
+
sq
(
d1
)
+
sq
(
d2
);
}
Real
kdtree_get_pt
(
const
size_t
idx
,
int
dim
)
const
{
return
appearance
[
idx
].
point
[
dim
];
}
template
<
class
BBOX
>
bool
kdtree_get_bbox
(
BBOX
&
bb
)
const
{
bb
[
0
].
low
=
index
.
aabbMin
[
0
];
bb
[
1
].
low
=
index
.
aabbMin
[
1
];
bb
[
2
].
low
=
index
.
aabbMin
[
2
];
bb
[
0
].
high
=
index
.
aabbMax
[
0
];
bb
[
1
].
high
=
index
.
aabbMax
[
1
];
bb
[
2
].
high
=
index
.
aabbMax
[
2
];
return
true
;
}
};
};
...
@@ -73,6 +138,17 @@ protected:
...
@@ -73,6 +138,17 @@ protected:
*****************************************************************************************/
*****************************************************************************************/
ParticleEffect
::
ParticleEffect
()
:
index
(
*
this
)
{}
ParticleEffect
::
Index
::
Index
(
ParticleEffect
&
e
)
:
aabbMin
(
0
,
0
,
0
),
aabbMax
(
0
,
0
,
0
),
radiusMax
(
0
),
tree
(
3
,
e
)
{}
inline
float
ParticleEffect
::
kernel
(
float
q
)
inline
float
ParticleEffect
::
kernel
(
float
q
)
{
{
float
a
=
1
-
q
*
q
;
float
a
=
1
-
q
*
q
;
...
@@ -91,17 +167,47 @@ inline float ParticleEffect::kernelDerivative(float q)
...
@@ -91,17 +167,47 @@ inline float ParticleEffect::kernelDerivative(float q)
return
-
6.0
f
*
q
*
a
*
a
;
return
-
6.0
f
*
q
*
a
*
a
;
}
}
inline
void
ParticleEffect
::
beginFrame
(
const
FrameInfo
&
f
)
{
// Measure bounding box and largest radius in 'particles'
index
.
aabbMin
=
appearance
[
0
].
point
;
index
.
aabbMax
=
appearance
[
0
].
point
;
index
.
radiusMax
=
appearance
[
0
].
radius
;
for
(
unsigned
i
=
1
;
i
<
appearance
.
size
();
++
i
)
{
const
ParticleAppearance
&
particle
=
appearance
[
i
];
index
.
aabbMin
[
0
]
=
std
::
min
(
index
.
aabbMin
[
0
],
particle
.
point
[
0
]);
index
.
aabbMin
[
1
]
=
std
::
min
(
index
.
aabbMin
[
1
],
particle
.
point
[
1
]);
index
.
aabbMin
[
2
]
=
std
::
min
(
index
.
aabbMin
[
2
],
particle
.
point
[
2
]);
index
.
aabbMax
[
0
]
=
std
::
max
(
index
.
aabbMax
[
0
],
particle
.
point
[
0
]);
index
.
aabbMax
[
1
]
=
std
::
max
(
index
.
aabbMax
[
1
],
particle
.
point
[
1
]);
index
.
aabbMax
[
2
]
=
std
::
max
(
index
.
aabbMax
[
2
],
particle
.
point
[
2
]);
index
.
radiusMax
=
std
::
max
(
index
.
radiusMax
,
particle
.
radius
);
}
// Rebuild KD-tree
index
.
tree
.
buildIndex
();
// Reset debug counters
particlesPerPixelNumerator
=
0
;
particlesPerPixelDenominator
=
0
;
}
inline
void
ParticleEffect
::
calculatePixel
(
Vec3
&
rgb
,
const
PixelInfo
&
p
)
inline
void
ParticleEffect
::
calculatePixel
(
Vec3
&
rgb
,
const
PixelInfo
&
p
)
{
{
Vec3
accumulator
(
0
,
0
,
0
);
Vec3
accumulator
(
0
,
0
,
0
);
Vec3
point
=
p
.
point
;
std
::
vector
<
ParticleAppearance
>::
iterator
i
=
appearance
.
begin
();
std
::
vector
<
ParticleAppearance
>::
iterator
e
=
appearance
.
end
();
for
(;
i
!=
e
;
++
i
)
{
std
::
vector
<
std
::
pair
<
size_t
,
Real
>
>
hits
;
ParticleAppearance
&
particle
=
*
i
;
nanoflann
::
SearchParams
params
;
float
dist2
=
sqrlen
(
particle
.
point
-
point
);
params
.
sorted
=
false
;
unsigned
numHits
=
index
.
tree
.
radiusSearch
(
&
p
.
point
[
0
],
sq
(
index
.
radiusMax
),
hits
,
params
);
for
(
unsigned
i
=
0
;
i
<
numHits
;
i
++
)
{
ParticleAppearance
&
particle
=
appearance
[
hits
[
i
].
first
];
float
dist2
=
hits
[
i
].
second
;
// Normalized distance
// Normalized distance
float
q2
=
dist2
/
sq
(
particle
.
radius
);
float
q2
=
dist2
/
sq
(
particle
.
radius
);
...
@@ -111,4 +217,15 @@ inline void ParticleEffect::calculatePixel(Vec3& rgb, const PixelInfo& p)
...
@@ -111,4 +217,15 @@ inline void ParticleEffect::calculatePixel(Vec3& rgb, const PixelInfo& p)
}
}
rgb
=
accumulator
;
rgb
=
accumulator
;
particlesPerPixelNumerator
+=
numHits
;
particlesPerPixelDenominator
++
;
}
inline
void
ParticleEffect
::
debug
(
const
DebugInfo
&
d
)
{
fprintf
(
stderr
,
"
\t
[particle] %.1f kB, radius=%.1f, %.2f hits/pixel
\n
"
,
index
.
tree
.
usedMemory
()
/
1024.0
f
,
index
.
radiusMax
,
float
(
particlesPerPixelNumerator
)
/
float
(
particlesPerPixelDenominator
));
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment