Skip to content

Commit 072fac9

Browse files
author
Paul Wheeler
committed
Added normal function for specifying explicit normals while drawing 3d shapes with vertex.
1 parent 93cfc53 commit 072fac9

File tree

4 files changed

+134
-13
lines changed

4 files changed

+134
-13
lines changed

src/core/shape/vertex.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,4 +992,56 @@ p5.prototype.vertex = function(x, y, moveTo, u, v) {
992992
return this;
993993
};
994994

995+
/**
996+
* Sets the 3d vertex normal to use for subsequent vertices drawn with
997+
* <a href="#/p5/vertex">vertex()</a>. A normal is a vector that is generally
998+
* nearly perpendicular to a shape's surface which controls how much light will
999+
* be reflected from that part of the surface.
1000+
*
1001+
* @method normal
1002+
* @param {Vector} vector A p5.Vector representing the vertex normal.
1003+
* @chainable
1004+
* @example
1005+
* <div>
1006+
* <code>
1007+
* function setup() {
1008+
* createCanvas(100, 100, WEBGL);
1009+
* noStroke();
1010+
* }
1011+
*
1012+
* function draw() {
1013+
* background(255);
1014+
* rotateY(frameCount / 100);
1015+
* normalMaterial();
1016+
* beginShape(TRIANGLE_STRIP);
1017+
* normal(-0.4, 0.4, 0.8);
1018+
* vertex(-30, 30, 0);
1019+
*
1020+
* normal(0, 0, 1);
1021+
* vertex(-30, -30, 30);
1022+
* vertex(30, 30, 30);
1023+
*
1024+
* normal(0.4, -0.4, 0.8);
1025+
* vertex(30, -30, 0);
1026+
* endShape();
1027+
* }
1028+
* </code>
1029+
* </div>
1030+
*/
1031+
1032+
/**
1033+
* @method normal
1034+
* @param {Number} x The x component of the vertex normal.
1035+
* @param {Number} y The y component of the vertex normal.
1036+
* @param {Number} z The z component of the vertex normal.
1037+
* @chainable
1038+
*/
1039+
p5.prototype.normal = function(x, y, z) {
1040+
this._assert3d('normal');
1041+
p5._validateParameters('normal', arguments);
1042+
this._renderer.normal(...arguments);
1043+
1044+
return this;
1045+
};
1046+
9951047
export default p5;

src/webgl/p5.RendererGL.Immediate.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ p5.RendererGL.prototype.vertex = function(x, y) {
6767
}
6868
const vert = new p5.Vector(x, y, z);
6969
this.immediateMode.geometry.vertices.push(vert);
70+
this.immediateMode.geometry.vertexNormals.push(this._currentNormal);
7071
const vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0];
7172
this.immediateMode.geometry.vertexColors.push(
7273
vertexColor[0],
@@ -103,6 +104,28 @@ p5.RendererGL.prototype.vertex = function(x, y) {
103104
return this;
104105
};
105106

107+
/**
108+
* Sets the normal to use for subsequent vertices.
109+
* @method vertexNormal
110+
* @param {Number} x
111+
* @param {Number} y
112+
* @param {Number} z
113+
* @chainable
114+
*
115+
* @method vertexNormal
116+
* @param {Vector} v
117+
* @chainable
118+
*/
119+
p5.RendererGL.prototype.normal = function(xorv, y, z) {
120+
if (xorv instanceof p5.Vector) {
121+
this._currentNormal = xorv;
122+
} else {
123+
this._currentNormal = new p5.Vector(xorv, y, z);
124+
}
125+
126+
return this;
127+
};
128+
106129
/**
107130
* End shape drawing and render vertices to screen.
108131
* @chainable
@@ -251,7 +274,6 @@ p5.RendererGL.prototype._drawImmediateFill = function() {
251274
const gl = this.GL;
252275
const shader = this._getImmediateFillShader();
253276

254-
this._calculateNormals(this.immediateMode.geometry);
255277
this._setFillUniforms(shader);
256278

257279
for (const buff of this.immediateMode.buffers.fill) {
@@ -298,16 +320,4 @@ p5.RendererGL.prototype._drawImmediateStroke = function() {
298320
shader.unbindShader();
299321
};
300322

301-
/**
302-
* Called from _drawImmediateFill(). Currently adds default normals which
303-
* only work for flat shapes.
304-
* @parem
305-
* @private
306-
*/
307-
p5.RendererGL.prototype._calculateNormals = function(geometry) {
308-
geometry.vertices.forEach(() => {
309-
geometry.vertexNormals.push(new p5.Vector(0, 0, 1));
310-
});
311-
};
312-
313323
export default p5.RendererGL;

src/webgl/p5.RendererGL.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ p5.RendererGL = function(elt, pInst, isMainCanvas, attr) {
122122
this.uPMatrix = new p5.Matrix();
123123
this.uNMatrix = new p5.Matrix('mat3');
124124

125+
// Current vertex normal
126+
this._currentNormal = new p5.Vector(0, 0, 1);
127+
125128
// Camera
126129
this._curCamera = new p5.Camera(this);
127130
this._curCamera._computeCameraDefaultSettings();
@@ -1026,6 +1029,8 @@ p5.RendererGL.prototype.push = function() {
10261029
properties._tex = this._tex;
10271030
properties.drawMode = this.drawMode;
10281031

1032+
properties._currentNormal = this._currentNormal;
1033+
10291034
return style;
10301035
};
10311036

test/unit/webgl/normal.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
suite('', function() {
2+
var myp5;
3+
4+
if (!window.Modernizr.webgl) {
5+
return;
6+
}
7+
8+
setup(function() {
9+
myp5 = new p5(function(p) {
10+
p.setup = function() {
11+
p.createCanvas(100, 100, p.WEBGL);
12+
};
13+
});
14+
});
15+
16+
teardown(function() {
17+
myp5.remove();
18+
});
19+
20+
suite('p5.prototype.normal', function() {
21+
test('should be a function', function() {
22+
assert.ok(myp5.normal);
23+
assert.typeOf(myp5.normal, 'function');
24+
});
25+
test('missing param #1', function() {
26+
assert.validationError(function() {
27+
myp5.normal(10);
28+
});
29+
});
30+
test('wrong param type at #0', function() {
31+
assert.validationError(function() {
32+
myp5.normal('a', 1);
33+
});
34+
});
35+
test('accepts numeric arguments', function() {
36+
assert.doesNotThrow(
37+
function() {
38+
myp5.normal(0, 1, 0);
39+
},
40+
Error,
41+
'got unwanted exception'
42+
);
43+
});
44+
test('accepts vector argument', function() {
45+
assert.doesNotThrow(
46+
function() {
47+
myp5.normal(myp5.createVector(0, 1, 0));
48+
},
49+
Error,
50+
'got unwanted exception'
51+
);
52+
});
53+
});
54+
});

0 commit comments

Comments
 (0)