Skip to content

Commit 5fb6619

Browse files
committed
added support for functions that specify curvature
1 parent ee31512 commit 5fb6619

File tree

3 files changed

+60
-14
lines changed

3 files changed

+60
-14
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@ To get started, include the minified javascript in your a-frame project.
2626

2727
# Usage
2828

29-
Every low-poly object supports the following attributes:
30-
31-
**`position-function: function(x, y, z)`**
32-
33-
Function that accepts the vertex's *original position* and outputs the vertex's new position, or *root position*. This is applied *before* customizable randomization. All random perturbations are applied to the vertex's root position.
29+
Every low-poly object supports the following attributes. Modify the following attributes just like you would any other AFrame VR attribute:
3430

3531
**`max-amplitude: <x double> <y double> <z double>`**
3632

@@ -42,6 +38,10 @@ Maximum and minimum amount of perturbation allowed for each vertex. The vertex w
4238

4339
Seed for random-number generator, allowing you to fix randomness during design
4440

41+
**`position-function: function({x, y, z, min: {x, y, z}, max: {x, y, z}})`**
42+
43+
Function that accepts the vertex's *original position* and outputs the vertex's new position, or *root position*. This is applied *before* customizable randomization. All random perturbations are applied to the vertex's root position.
44+
4545
> **`max-amplitude-difference: <x double> <y double> <z double>`** *coming soon*
4646
>
4747
> **`min-amplitude-difference: <x double> <y double> <z double>`** *coming soon*

demo/index.html

+14-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@
1616
<!-- Google Analytics -->
1717
<script>
1818
$(document).ready(function() {
19-
var t =0;
19+
// setup "sky" so that it's sinusoidal
20+
document.querySelector('#ground').setAttribute('position-function', function (position) {
21+
var py = (position.y - position.min.y) / (position.max.y - position.min.y);
22+
var z1 = Math.sin(py * 2 * Math.PI) * 1 + position.min.z;
23+
return {x: position.x, y: position.y, z: z1}
24+
});
25+
26+
// change seed every second
27+
var t = 0;
2028
setInterval(function() {
2129
t += 1;
2230
seed = 'seed' + t;
@@ -68,18 +76,18 @@
6876
</lp-sphere>
6977
<a-entity class="tree" position="0 1 0">
7078
<lp-cylinder class="trunk reseed" radius-top="0.01" radius-bottom="0.1" height="2" color="#A5602D"></lp-cylinder>
71-
<lp-cone class="reseed" radius="0.35" height="1" segments-height="5" amplitude="0.02" mixin="foliage" position="0 1.4 0"></lp-cone>
79+
<lp-cone class="reseed" radius="0.35" height="1" segments-height="5" mixin="foliage" position="0 1.4 0"></lp-cone>
7280
<lp-cone class="reseed" radius="0.5" height="0.8" segments-height="3" mixin="foliage" position="0 0.8 0" seed="1"></lp-cone>
7381
<lp-cone class="reseed" radius="0.6" height="0.8" segments-height="3" mixin="foliage" position="0 0.4 0" seed="2"></lp-cone>
7482
<lp-cone class="reseed" radius="0.7" height="0.8" segments-height="3" mixin="foliage" position="0 0 0" seed="3"></lp-cone>
7583
</a-entity>
7684
<a-entity class="tree" scale="0.75 0.75 0.75" position="1 0.75 0">
7785
<lp-cylinder class="trunk reseed" radius-top="0.02" radius-bottom="0.3" height="2.5" color="#795110" position="0 0.25 0"></lp-cylinder>
78-
<lp-sphere class="reseed" position="0 0.6 0" color="#59810C" radius="1" segments-width="10" segments-height="10" amplitude="0.2" low-poly-sphere></lp-sphere>
86+
<lp-sphere class="reseed" position="0 0.6 0" color="#59810C" radius="1" segments-width="10" segments-height="10" low-poly-sphere></lp-sphere>
7987
</a-entity>
8088
<a-entity class="tree" scale="0.75 0.75 0.75" position="0 0.75 -1">
8189
<lp-cylinder class="trunk reseed" radius-top="0.02" radius-bottom="0.3" height="2.5" color="#795110" position="0 0.25 0"></lp-cylinder>
82-
<lp-sphere class="reseed" position="0 0.8 0" color="#59810C" radius="1" segments-width="8" segments-height="8" amplitude="0.2" low-poly-sphere></lp-sphere>
90+
<lp-sphere class="reseed" position="0 0.8 0" color="#59810C" radius="1" segments-width="8" segments-height="8" low-poly-sphere></lp-sphere>
8391
</a-entity>
8492
<a-entity class="rocks">
8593
<lp-sphere class="reseed" color="#666" radius="0.25" position="0 0 1"></lp-sphere>
@@ -118,6 +126,8 @@
118126
<lp-sphere class="reseed" color="#f4cb6b" radius="0.6"></lp-sphere>
119127
<a-animation attribute="position" from="2 3 0" to="2 2.5 0" direction="alternate" repeat="indefinite" dur="5000"></a-animation>
120128
</a-entity>
129+
130+
<lp-plane id="ground" color="#609af7" rotation="0 0 90" position="0 0 -3" width="10" height="10" max-amplitude="0.5 0.5 0.25"></lp-plane>
121131
</a-scene>
122132
</body>
123133
</html>

src/main.js

+41-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ class LowPoly {
44
return Object.assign({}, mapping, {
55
'max-amplitude' : name + '.maxAmplitude',
66
'min-amplitude' : name + '.minAmplitude',
7+
'position-function' : name + '.positionFunction',
78
'seed' : name + '.seed',
89
});
910
}
@@ -15,7 +16,7 @@ class LowPoly {
1516
// Randomness amplitude and variance.
1617
maxAmplitude : {default: {x: 0.1, y: 0.1, z: 0.1}, type: 'vec3'},
1718
minAmplitude : {default: {x: 0, y: 0, z: 0}, type: 'vec3'},
18-
positionFunction : {default: (x, y, z) => { return {x: x, y: y, z: z} }},
19+
positionFunction : {default: position => { return {x: position.x, y: position.y, z: position.z} }},
1920
amplitudePDF : {default: p => p},
2021

2122
// Material.
@@ -60,18 +61,42 @@ class LowPoly {
6061

6162
static randomizeVertices(data, geometry) {
6263
Random.seed(data.seed);
64+
var min = LowPoly.computeMinPosition(geometry.vertices);
65+
var max = LowPoly.computeMaxPosition(geometry.vertices);
6366
for (let v, i = 0, l = geometry.vertices.length; i < l; i++) {
6467
v = geometry.vertices[i];
6568

66-
var root = LowPoly.computeRootPosition(v, data.positionFunction);
69+
var root = LowPoly.computeRootPosition(v, data.positionFunction, min, max);
6770
LowPoly.randomizeVertexDimension(v, 'x', root.x, data.amplitudePDF, data.maxAmplitude.x, data.minAmplitude.x);
6871
LowPoly.randomizeVertexDimension(v, 'y', root.y, data.amplitudePDF, data.maxAmplitude.y, data.minAmplitude.y);
6972
LowPoly.randomizeVertexDimension(v, 'z', root.z, data.amplitudePDF, data.maxAmplitude.z, data.minAmplitude.z);
7073
}
7174
geometry.verticesNeedUpdate = true;
7275
}
7376

74-
static computeRootPosition(vertex, positionFunction) {
77+
static computeMinPosition(vertices) {
78+
var min = {x: Infinity, y: Infinity, z: Infinity};
79+
for (let v, i = 0, l = vertices.length; i < l; i++) {
80+
v = vertices[i];
81+
min.x = Math.min(v.x, min.x);
82+
min.y = Math.min(v.y, min.y);
83+
min.z = Math.min(v.z, min.z);
84+
}
85+
return min;
86+
}
87+
88+
static computeMaxPosition(vertices) {
89+
var max = {x: -Infinity, y: -Infinity, z: -Infinity};
90+
for (let v, i = 0, l = vertices.length; i < l; i++) {
91+
v = vertices[i];
92+
max.x = Math.max(v.x, max.x);
93+
max.y = Math.max(v.y, max.y);
94+
max.z = Math.max(v.z, max.z);
95+
}
96+
return max;
97+
}
98+
99+
static computeRootPosition(vertex, positionFunction, min, max) {
75100

76101
['x', 'y', 'z'].forEach(function (dimension) {
77102
var key = 'o' + dimension;
@@ -80,13 +105,24 @@ class LowPoly {
80105
}
81106
})
82107

83-
return positionFunction(vertex['ox'], vertex['oy'], vertex['oz'])
108+
// TODO: hack to support funnctions in attributes... not a good idea
109+
if (typeof positionFunction === 'string') {
110+
eval("positionFunction = " + positionFunction);
111+
}
112+
113+
return positionFunction({
114+
x: vertex['ox'],
115+
y: vertex['oy'],
116+
z: vertex['oz'],
117+
min: min,
118+
max: max
119+
})
84120
}
85121

86122
static randomizeVertexDimension(vertex, dimension, root, amplitudePDF, maxAmplitude, minAmplitude) {
87123
let p = amplitudePDF(Random.random());
88124
let amp = (maxAmplitude - minAmplitude) * p + minAmplitude;
89-
var value = vertex['o' + dimension];
125+
var value = root;
90126
vertex[dimension] = value + amp;
91127
}
92128
}

0 commit comments

Comments
 (0)