Skip to content

Commit

Permalink
Add convenience function for text to 3D model
Browse files Browse the repository at this point in the history
  • Loading branch information
davepagurek committed Dec 18, 2024
1 parent 03f2848 commit 37c1016
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 17 deletions.
27 changes: 12 additions & 15 deletions preview/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,22 @@
import p5 from '../src/app.js';

const sketch = function (p) {
p.setup = function () {
p.createCanvas(100, 100, p.WEBGL);
let font, geom;
p.setup = async function () {
font = await p.loadFont('font/Lato-Black.ttf');
p.createCanvas(400, 400, p.WEBGL);
p.textSize(120);
p.textAlign(p.CENTER)
geom = font.textToModel('p5*js', 0, 0, { extrude: 20 });
};

p.draw = function () {
p.background(200);
p.strokeCap(p.SQUARE);
p.strokeJoin(p.MITER);
p.translate(-p.width/2, -p.height/2);
p.noStroke();
p.beginShape();
p.bezierOrder(2);
p.fill('red');
p.vertex(10, 10);
p.fill('lime');
p.bezierVertex(40, 25);
p.fill('blue');
p.bezierVertex(10, 40);
p.endShape();
p.normalMaterial();
p.drawingContext.enable(p.drawingContext.CULL_FACE);
p.drawingContext.cullFace(p.drawingContext.FRONT);
p.orbitControl();
p.model(geom);
};
};

Expand Down
58 changes: 56 additions & 2 deletions src/type/p5.Font.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ function font(p5, fn) {
}, []);
}

textToContours(str, x, y, width, height, options) {
textToContours(str, x = 0, y = 0, width, height, options) {
({ width, height, options } = this._parseArgs(width, height, options));

const cmds = this.textToPaths(str, x, y, width, height, options);
Expand All @@ -154,6 +154,60 @@ function font(p5, fn) {
return cmdContours.map((commands) => pathToPoints(commands, options));
}

textToModel(str, x, y, width, height, options) {
({ width, height, options } = this._parseArgs(width, height, options));
const extrude = options?.extrude || 0;
const contours = this.textToContours(str, x, y, width, height, options);
const geom = this._pInst.buildGeometry(() => {
if (extrude === 0) {
this._pInst.beginShape();
this._pInst.normal(0, 0, 1);
for (const contour of contours) {
this._pInst.beginContour();
for (const { x, y } of contour) {
this._pInst.vertex(x, y);
}
this._pInst.endContour(this._pInst.CLOSE);
}
this._pInst.endShape();
} else {
// Draw front faces
for (const side of [1, -1]) {
this._pInst.beginShape();
for (const contour of contours) {
this._pInst.beginContour();
for (const { x, y } of contour) {
this._pInst.vertex(x, y, side * extrude * 0.5);
}
this._pInst.endContour(this._pInst.CLOSE);
}
this._pInst.endShape();
this._pInst.beginShape();
}
// Draw sides
for (const contour of contours) {
this._pInst.beginShape(this._pInst.QUAD_STRIP);
for (const v of contour) {
for (const side of [-1, 1]) {
this._pInst.vertex(v.x, v.y, side * extrude * 0.5);
}
}
this._pInst.endShape();
}
}
});
if (extrude !== 0) {
geom.computeNormals();
for (const face of geom.faces) {
if (face.every((idx) => geom.vertices[idx].z <= -extrude * 0.5 + 0.1)) {
for (const idx of face) geom.vertexNormals[idx].set(0, 0, -1);
face.reverse();
}
}
}
return geom;
}

static async list(log = false) { // tmp
if (log) {
console.log('There are', document.fonts.size, 'font-faces\n');
Expand Down Expand Up @@ -370,7 +424,7 @@ function font(p5, fn) {

_measureTextDefault(renderer, str) {
let { textAlign, textBaseline } = renderer.states;
let ctx = renderer.drawingContext;
let ctx = renderer.textDrawingContext();
ctx.textAlign = 'left';
ctx.textBaseline = 'alphabetic';
let metrics = ctx.measureText(str);
Expand Down
39 changes: 39 additions & 0 deletions test/unit/visual/cases/webgl.js
Original file line number Diff line number Diff line change
Expand Up @@ -492,4 +492,43 @@ visualSuite('WebGL', function() {
});
}
});

visualSuite('textToModel', () => {
visualTest('Flat', async (p5, screenshot) => {
p5.createCanvas(50, 50, p5.WEBGL);
const font = await p5.loadFont(
'/unit/assets/Inconsolata-Bold.ttf'
);
p5.textSize(20);
p5.textAlign(p5.CENTER, p5.CENTER);
const geom = font.textToModel('p5*js', 0, 0, {
sampleFactor: 2
});
p5.background(255);
p5.normalMaterial();
p5.rotateX(p5.PI*0.1);
p5.rotateY(p5.PI*0.1);
p5.model(geom);
screenshot();
});

visualTest('Extruded', async (p5, screenshot) => {
p5.createCanvas(50, 50, p5.WEBGL);
const font = await p5.loadFont(
'/unit/assets/Inconsolata-Bold.ttf'
);
p5.textSize(20);
p5.textAlign(p5.CENTER, p5.CENTER);
const geom = font.textToModel('p5*js', 0, 0, {
extrude: 10,
sampleFactor: 2
});
p5.background(255);
p5.normalMaterial();
p5.rotateX(p5.PI*0.1);
p5.rotateY(p5.PI*0.1);
p5.model(geom);
screenshot();
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"numScreenshots": 1
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"numScreenshots": 1
}

0 comments on commit 37c1016

Please sign in to comment.