From ef33f8e38465276bd4faac3bfec7b32cf06be5d5 Mon Sep 17 00:00:00 2001 From: Nixxx19 <185968020+Nixxx19@users.noreply.github.com> Date: Sun, 7 Jun 2026 17:54:06 +0530 Subject: [PATCH 1/4] render multi-material models per part --- src/core/p5.Renderer3D.js | 48 +++++++++++++++++++++++++++++- src/webgl/loading.js | 7 +++-- src/webgl/p5.Geometry.js | 40 +++++++------------------ src/webgl/p5.GeometryPart.js | 13 ++++++++ test/unit/assets/textured.mtl | 3 ++ test/unit/assets/textured.obj | 4 +++ test/unit/io/loadModel.js | 14 +++++---- test/unit/webgl/p5.GeometryPart.js | 28 +++++++++++++++-- 8 files changed, 115 insertions(+), 42 deletions(-) diff --git a/src/core/p5.Renderer3D.js b/src/core/p5.Renderer3D.js index 363773befc..9cba0effd7 100644 --- a/src/core/p5.Renderer3D.js +++ b/src/core/p5.Renderer3D.js @@ -589,7 +589,28 @@ export class Renderer3D extends Renderer { geometry.vertices.length >= 3 && ![constants.LINES, constants.POINTS].includes(mode) ) { - this._drawFills(geometry, { mode, count }); + // draw every part. a part with no material state draws straight (no + // push/pop); a single-material geometry is its own part, so that case is + // exactly the old single draw. multi-material parts each apply their own + // material around the draw. + const parts = geometry.parts && geometry.parts.length + ? geometry.parts + : [geometry]; + for (const part of parts) { + const state = part.partState; + const hasMaterial = state && ( + state.fill || state.texture || state.ambientColor || + state.specularColor || state.shininess != null + ); + if (hasMaterial) { + this.push(); + this._applyPartState(state); + this._drawFills(part, { mode, count }); + this.pop(); + } else { + this._drawFills(part, { mode, count }); + } + } } if (this.states.strokeColor && geometry.lineVertices.length >= 1) { @@ -628,6 +649,31 @@ export class Renderer3D extends Renderer { shader.unbindShader(); } + // apply a part's material to the renderer before it's drawn. only non-null + // fields are set, so an empty part state leaves the uniforms untouched. + _applyPartState(partState) { + if (!partState) return; + if (partState.fill) { + const c = partState.fill; + this.states.setValue('curFillColor', [c[0], c[1], c[2], 1]); + } + if (partState.texture) { + this.states.setValue('_tex', partState.texture); + this.states.setValue('drawMode', constants.TEXTURE); + } + if (partState.ambientColor) { + this.states.setValue('curAmbientColor', partState.ambientColor); + this.states.setValue('_hasSetAmbient', true); + } + if (partState.specularColor) { + this.states.setValue('curSpecularColor', partState.specularColor); + this.states.setValue('_useSpecularMaterial', true); + } + if (partState.shininess != null) { + this.states.setValue('_useShininess', partState.shininess); + } + } + _drawStrokes(geometry, { count } = {}) { this._useLineColor = geometry.vertexStrokeColors.length > 0; diff --git a/src/webgl/loading.js b/src/webgl/loading.js index 4e8e799db5..8dcc23583d 100755 --- a/src/webgl/loading.js +++ b/src/webgl/loading.js @@ -131,10 +131,11 @@ async function loadMaterialTextures(materials, modelPath, instance) { // as the aggregate; each part gets its own localised verts with faces re-indexed // against them, plus its material's state. function buildMaterialParts(model, faceMaterials, materials) { - // one group per material, plus a null group for faces before any usemtl so - // none get dropped. no materials at all -> keep the default wrap. + // only split when there are genuinely multiple materials. a single material + // (or none) stays as the geometry's own part and renders as before. one group + // per material, plus a null group for faces before any usemtl so none drop. const names = [...new Set(faceMaterials)]; - if (!names.some(name => name != null)) return; + if (names.filter(name => name != null).length < 2) return; const hasUvs = model.uvs.length > 0; const hasNormals = model.vertexNormals.length > 0; diff --git a/src/webgl/p5.Geometry.js b/src/webgl/p5.Geometry.js index 73d601e3bf..58b1003796 100644 --- a/src/webgl/p5.Geometry.js +++ b/src/webgl/p5.Geometry.js @@ -8,7 +8,7 @@ import * as constants from '../core/constants'; import { DataArray } from './p5.DataArray'; -import { GeometryPart } from './p5.GeometryPart'; +import { createPartState } from './p5.GeometryPart'; import { Vector } from '../math/p5.Vector'; import { downloadFile } from '../io/utilities'; @@ -65,9 +65,13 @@ class Geometry { this.gid = `_p5_Geometry_${Geometry.nextId}`; Geometry.nextId++; + // a geometry can act as its own single part: this is the default material + // state used when it is drawn that way (see _wrapInSinglePart). + this.partState = createPartState(); + // every geometry is one or more parts (see p5.GeometryPart). loaders that // know about materials fill parts themselves; anything built the old way - // gets wrapped in a single part below. + // becomes its own single part below. this.parts = []; if (callback instanceof Function) { @@ -79,35 +83,11 @@ class Geometry { } } - // wrap this geometry's own buffers in one part, for anything built the old way - // (primitives, new p5.Geometry(cb)). the part is a live view onto our arrays, - // not a copy, so reassigning an array or changing gid later can't desync it. + // a geometry with no material breakdown is its own single part. using the + // geometry itself (rather than a wrapper) means drawing the part is exactly + // drawing the geometry: same buffers, gid, dirty flags and custom attributes. _wrapInSinglePart() { - const geometry = this; - const part = new GeometryPart(`${this.gid}|part0`); - for (const field of [ - 'vertices', - 'vertexNormals', - 'faces', - 'uvs', - 'vertexColors' - ]) { - Object.defineProperty(part, field, { - get() { - return geometry[field]; - }, - enumerable: true, - configurable: true - }); - } - Object.defineProperty(part, 'gid', { - get() { - return `${geometry.gid}|part0`; - }, - enumerable: true, - configurable: true - }); - this.parts = [part]; + this.parts = [this]; } /** diff --git a/src/webgl/p5.GeometryPart.js b/src/webgl/p5.GeometryPart.js index 748121fd78..2e81fe52f8 100644 --- a/src/webgl/p5.GeometryPart.js +++ b/src/webgl/p5.GeometryPart.js @@ -32,6 +32,19 @@ class GeometryPart { this.partState = partState || createPartState(); this.dirtyFlags = {}; + + // custom per-vertex attributes (p5.strands). empty for parsed parts; the + // single-part wrap points this back at the parent geometry. + this.userVertexProperties = {}; + } + + // the renderer needs this to pick a blend mode. a part is transparent if any + // of its vertex colors has alpha below 1. + hasFillTransparency() { + for (let i = 3; i < this.vertexColors.length; i += 4) { + if (this.vertexColors[i] < 1) return true; + } + return false; } } diff --git a/test/unit/assets/textured.mtl b/test/unit/assets/textured.mtl index 4dd92e97dd..409ccd391d 100644 --- a/test/unit/assets/textured.mtl +++ b/test/unit/assets/textured.mtl @@ -2,3 +2,6 @@ newmtl mat0 Kd 1 1 1 Ns 50 map_Kd cat.jpg + +newmtl mat1 +Kd 1 0 0 diff --git a/test/unit/assets/textured.obj b/test/unit/assets/textured.obj index 65d6fa38b9..2f8554b0e2 100644 --- a/test/unit/assets/textured.obj +++ b/test/unit/assets/textured.obj @@ -2,8 +2,12 @@ mtllib textured.mtl v 0 0 0 v 1 0 0 v 0 1 0 +v 1 1 0 vt 0 0 vt 1 0 vt 0 1 +vt 1 1 usemtl mat0 f 1/1 2/2 3/3 +usemtl mat1 +f 2/2 4/4 3/3 diff --git a/test/unit/io/loadModel.js b/test/unit/io/loadModel.js index 9538021405..0679b6516a 100644 --- a/test/unit/io/loadModel.js +++ b/test/unit/io/loadModel.js @@ -112,10 +112,12 @@ suite('loadModel', function() { }; try { const model = await mockP5Prototype.loadModel('/test/unit/assets/textured.obj'); - // single material -> one part carrying that material's state - assert.equal(model.parts.length, 1); - assert.equal(model.parts[0].partState.texture, fakeImage); - assert.equal(model.parts[0].partState.shininess, 50); + // two materials, so two parts; the textured one carries the image. + assert.equal(model.parts.length, 2); + const textured = model.parts.find(p => p.partState.texture); + assert.ok(textured, 'a part has the loaded texture'); + assert.equal(textured.partState.texture, fakeImage); + assert.equal(textured.partState.shininess, 50); } finally { delete mockP5Prototype.loadImage; } @@ -127,8 +129,8 @@ suite('loadModel', function() { }; try { const model = await mockP5Prototype.loadModel('/test/unit/assets/textured.obj'); - assert.equal(model.parts.length, 1); - assert.equal(model.parts[0].partState.texture, null); + assert.equal(model.parts.length, 2); + assert.ok(model.parts.every(p => p.partState.texture == null)); } finally { delete mockP5Prototype.loadImage; } diff --git a/test/unit/webgl/p5.GeometryPart.js b/test/unit/webgl/p5.GeometryPart.js index ac7868f223..f2053d8f8a 100644 --- a/test/unit/webgl/p5.GeometryPart.js +++ b/test/unit/webgl/p5.GeometryPart.js @@ -1,4 +1,5 @@ import p5 from '../../../src/app.js'; +import { vi } from 'vitest'; suite('p5.GeometryPart', function() { let myp5; @@ -70,11 +71,12 @@ suite('p5.GeometryPart', function() { expect(geom.parts[0].faces).toBe(geom.faces); }); - test('the part gid tracks the geometry gid after it changes', function() { + test('a single-material geometry is its own part', function() { const geom = new p5.Geometry(undefined, undefined, undefined, myp5._renderer); geom.gid = 'my-model'; - expect(geom.parts[0].gid).toEqual('my-model|part0'); + expect(geom.parts[0]).toBe(geom); + expect(geom.parts[0].gid).toEqual('my-model'); }); test('a built-in primitive also gets one part', function() { @@ -85,4 +87,26 @@ suite('p5.GeometryPart', function() { expect(geom.parts[0].vertices.length).toEqual(1); }); }); + + suite('multi-material rendering', function() { + test('draws each part and passes the instance count through', async function() { + const renderer = myp5.createCanvas(50, 50, myp5.WEBGL); + const model = await new Promise(resolve => + myp5.loadModel('/test/unit/assets/octa-color.obj', resolve)); + + // octa-color has several materials, so several parts. + expect(model.parts.length).toBeGreaterThan(1); + + const spy = vi.spyOn(renderer, '_drawFills'); + myp5.background(255); + myp5.model(model, 4); + + // one fill draw per material part, each carrying the instance count. + expect(spy).toHaveBeenCalledTimes(model.parts.length); + for (const call of spy.mock.calls) { + expect(call[1].count).toEqual(4); + } + spy.mockRestore(); + }); + }); }); From c8f0ec2a2c6cfc1990283fb2ecf7d8eadd394541 Mon Sep 17 00:00:00 2001 From: nityam Date: Thu, 9 Jul 2026 12:03:28 +0530 Subject: [PATCH 2/4] address review: drop parts fallback, mtl fill alpha, geometrypart export, stroke test --- src/core/p5.Renderer3D.js | 18 +++++++++--------- src/webgl/index.js | 2 -- src/webgl/loading.js | 8 +++++++- src/webgl/p5.Geometry.js | 3 ++- src/webgl/p5.GeometryPart.js | 15 ++++----------- test/unit/webgl/p5.GeometryPart.js | 26 ++++++++++++++------------ 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/core/p5.Renderer3D.js b/src/core/p5.Renderer3D.js index 9cba0effd7..51d71e51ed 100644 --- a/src/core/p5.Renderer3D.js +++ b/src/core/p5.Renderer3D.js @@ -589,14 +589,11 @@ export class Renderer3D extends Renderer { geometry.vertices.length >= 3 && ![constants.LINES, constants.POINTS].includes(mode) ) { - // draw every part. a part with no material state draws straight (no - // push/pop); a single-material geometry is its own part, so that case is - // exactly the old single draw. multi-material parts each apply their own - // material around the draw. - const parts = geometry.parts && geometry.parts.length - ? geometry.parts - : [geometry]; - for (const part of parts) { + // draw every part. a geometry always has at least one part (the + // constructor makes it its own single part when nothing else does), so no + // fallback is needed. a part with no material state draws straight; + // multi-material parts apply their own material around the draw. + for (const part of geometry.parts) { const state = part.partState; const hasMaterial = state && ( state.fill || state.texture || state.ambientColor || @@ -655,7 +652,10 @@ export class Renderer3D extends Renderer { if (!partState) return; if (partState.fill) { const c = partState.fill; - this.states.setValue('curFillColor', [c[0], c[1], c[2], 1]); + // fills can carry alpha (a 4th component), e.g. an mtl `d` transparency + // or a fill(r, g, b, a) call. default to opaque when it's rgb only. + const alpha = c.length > 3 ? c[3] : 1; + this.states.setValue('curFillColor', [c[0], c[1], c[2], alpha]); } if (partState.texture) { this.states.setValue('_tex', partState.texture); diff --git a/src/webgl/index.js b/src/webgl/index.js index 97281c368a..9bf7a3c353 100644 --- a/src/webgl/index.js +++ b/src/webgl/index.js @@ -8,7 +8,6 @@ import renderBuffer from './p5.RenderBuffer'; import quat from './p5.Quat'; import matrix from '../math/p5.Matrix'; import geometry from './p5.Geometry'; -import geometryPart from './p5.GeometryPart'; import framebuffer from './p5.Framebuffer'; import dataArray from './p5.DataArray'; import camera from './p5.Camera'; @@ -29,7 +28,6 @@ export default function(p5){ p5.registerAddon(quat); p5.registerAddon(matrix); p5.registerAddon(geometry); - p5.registerAddon(geometryPart); p5.registerAddon(camera); p5.registerAddon(framebuffer); p5.registerAddon(dataArray); diff --git a/src/webgl/loading.js b/src/webgl/loading.js index 8dcc23583d..099e83e857 100755 --- a/src/webgl/loading.js +++ b/src/webgl/loading.js @@ -89,7 +89,13 @@ function parseMtlData(data) { function mtlToPartState(material) { const state = createPartState(); if (!material) return state; - if (material.diffuseColor) state.fill = material.diffuseColor; + if (material.diffuseColor) { + // carry the mtl transparency (d / Tr) in the fill's alpha. opaque materials + // stay rgb so nothing changes for them. + state.fill = material.opacity != null && material.opacity < 1 + ? [...material.diffuseColor, material.opacity] + : material.diffuseColor; + } if (material.ambientColor) state.ambientColor = material.ambientColor; if (material.specularColor) state.specularColor = material.specularColor; if (material.shininess !== undefined) state.shininess = material.shininess; diff --git a/src/webgl/p5.Geometry.js b/src/webgl/p5.Geometry.js index 58b1003796..646aa5afec 100644 --- a/src/webgl/p5.Geometry.js +++ b/src/webgl/p5.Geometry.js @@ -8,7 +8,7 @@ import * as constants from '../core/constants'; import { DataArray } from './p5.DataArray'; -import { createPartState } from './p5.GeometryPart'; +import { GeometryPart, createPartState } from './p5.GeometryPart'; import { Vector } from '../math/p5.Vector'; import { downloadFile } from '../io/utilities'; @@ -2122,6 +2122,7 @@ function geometry(p5, fn){ * } */ p5.Geometry = Geometry; + p5.GeometryPart = GeometryPart; /** * An array with the geometry's vertices. diff --git a/src/webgl/p5.GeometryPart.js b/src/webgl/p5.GeometryPart.js index 2e81fe52f8..a5acc890d7 100644 --- a/src/webgl/p5.GeometryPart.js +++ b/src/webgl/p5.GeometryPart.js @@ -38,9 +38,11 @@ class GeometryPart { this.userVertexProperties = {}; } - // the renderer needs this to pick a blend mode. a part is transparent if any - // of its vertex colors has alpha below 1. + // the renderer needs this to pick a blend mode. a part is transparent if its + // fill has alpha below 1, or any of its vertex colors does. hasFillTransparency() { + const fill = this.partState && this.partState.fill; + if (fill && fill.length > 3 && fill[3] < 1) return true; for (let i = 3; i < this.vertexColors.length; i += 4) { if (this.vertexColors[i] < 1) return true; } @@ -48,13 +50,4 @@ class GeometryPart { } } -function geometryPart(p5, fn) { - p5.GeometryPart = GeometryPart; -} - -export default geometryPart; export { GeometryPart, createPartState }; - -if (typeof p5 !== 'undefined') { - geometryPart(p5, p5.prototype); -} diff --git a/test/unit/webgl/p5.GeometryPart.js b/test/unit/webgl/p5.GeometryPart.js index f2053d8f8a..ca36364455 100644 --- a/test/unit/webgl/p5.GeometryPart.js +++ b/test/unit/webgl/p5.GeometryPart.js @@ -89,24 +89,26 @@ suite('p5.GeometryPart', function() { }); suite('multi-material rendering', function() { - test('draws each part and passes the instance count through', async function() { + test('draws a fill per part and a stroke for the model', async function() { const renderer = myp5.createCanvas(50, 50, myp5.WEBGL); - const model = await new Promise(resolve => - myp5.loadModel('/test/unit/assets/octa-color.obj', resolve)); + const model = await myp5.loadModel('/test/unit/assets/octa-color.obj'); // octa-color has several materials, so several parts. expect(model.parts.length).toBeGreaterThan(1); - const spy = vi.spyOn(renderer, '_drawFills'); + const fillSpy = vi.spyOn(renderer, '_drawFills'); + const strokeSpy = vi.spyOn(renderer, '_drawStrokes'); myp5.background(255); - myp5.model(model, 4); - - // one fill draw per material part, each carrying the instance count. - expect(spy).toHaveBeenCalledTimes(model.parts.length); - for (const call of spy.mock.calls) { - expect(call[1].count).toEqual(4); - } - spy.mockRestore(); + myp5.stroke(0); + myp5.model(model); + + // one fill draw per material part. + expect(fillSpy).toHaveBeenCalledTimes(model.parts.length); + // the model's outline is still stroked. + expect(strokeSpy).toHaveBeenCalled(); + + fillSpy.mockRestore(); + strokeSpy.mockRestore(); }); }); }); From e861e3cedccc022a6b54578762796e51d75974d5 Mon Sep 17 00:00:00 2001 From: nityam Date: Tue, 14 Jul 2026 10:50:37 +0530 Subject: [PATCH 3/4] make part fill always [r,g,b,a] and document part state types --- src/core/p5.Renderer3D.js | 16 +++++++++------- src/webgl/loading.js | 8 +++----- src/webgl/p5.GeometryPart.js | 15 ++++++++------- test/unit/io/loadModel.js | 4 ++-- test/unit/io/parseMtl.js | 2 +- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/core/p5.Renderer3D.js b/src/core/p5.Renderer3D.js index 51d71e51ed..7c2bc77b45 100644 --- a/src/core/p5.Renderer3D.js +++ b/src/core/p5.Renderer3D.js @@ -595,9 +595,13 @@ export class Renderer3D extends Renderer { // multi-material parts apply their own material around the draw. for (const part of geometry.parts) { const state = part.partState; + // fill/ambientColor/specularColor are arrays and texture is a p5.Image, + // so they're truthy when set; shininess is a number where 0 is valid. + // `!= null` keeps every field consistent and treats a 0 as present. const hasMaterial = state && ( - state.fill || state.texture || state.ambientColor || - state.specularColor || state.shininess != null + state.fill != null || state.texture != null || + state.ambientColor != null || state.specularColor != null || + state.shininess != null ); if (hasMaterial) { this.push(); @@ -651,11 +655,9 @@ export class Renderer3D extends Renderer { _applyPartState(partState) { if (!partState) return; if (partState.fill) { - const c = partState.fill; - // fills can carry alpha (a 4th component), e.g. an mtl `d` transparency - // or a fill(r, g, b, a) call. default to opaque when it's rgb only. - const alpha = c.length > 3 ? c[3] : 1; - this.states.setValue('curFillColor', [c[0], c[1], c[2], alpha]); + // fill is always [r, g, b, a] in 0..1, so it maps straight onto + // curFillColor (same shape/range as the array fill() sets). + this.states.setValue('curFillColor', partState.fill); } if (partState.texture) { this.states.setValue('_tex', partState.texture); diff --git a/src/webgl/loading.js b/src/webgl/loading.js index 099e83e857..a9a5e41904 100755 --- a/src/webgl/loading.js +++ b/src/webgl/loading.js @@ -90,11 +90,9 @@ function mtlToPartState(material) { const state = createPartState(); if (!material) return state; if (material.diffuseColor) { - // carry the mtl transparency (d / Tr) in the fill's alpha. opaque materials - // stay rgb so nothing changes for them. - state.fill = material.opacity != null && material.opacity < 1 - ? [...material.diffuseColor, material.opacity] - : material.diffuseColor; + // fill is always [r, g, b, a] in 0..1. the mtl d/Tr becomes the alpha, and + // opaque materials default to 1 so the format stays consistent either way. + state.fill = [...material.diffuseColor, material.opacity ?? 1]; } if (material.ambientColor) state.ambientColor = material.ambientColor; if (material.specularColor) state.specularColor = material.specularColor; diff --git a/src/webgl/p5.GeometryPart.js b/src/webgl/p5.GeometryPart.js index a5acc890d7..45664bf37e 100644 --- a/src/webgl/p5.GeometryPart.js +++ b/src/webgl/p5.GeometryPart.js @@ -5,14 +5,15 @@ */ // fresh part state. fields use p5 names (fill, texture...), not obj/mtl tokens. -// importers translate into this and drop anything we can't draw yet. +// importers translate into this and drop anything we can't draw yet. every color +// channel is 0..1 (same range as the renderer's curFillColor), not 0..255. function createPartState() { return { - fill: null, // Kd - ambientColor: null, // Ka - specularColor: null, // Ks - shininess: null, // Ns - texture: null // map_Kd + fill: null, // Kd + d -> [r, g, b, a] | null, each 0..1 + ambientColor: null, // Ka -> [r, g, b] | null, each 0..1 + specularColor: null, // Ks -> [r, g, b] | null, each 0..1 + shininess: null, // Ns -> number | null + texture: null // map_Kd -> p5.Image | null }; } @@ -42,7 +43,7 @@ class GeometryPart { // fill has alpha below 1, or any of its vertex colors does. hasFillTransparency() { const fill = this.partState && this.partState.fill; - if (fill && fill.length > 3 && fill[3] < 1) return true; + if (fill && fill[3] < 1) return true; for (let i = 3; i < this.vertexColors.length; i += 4) { if (this.vertexColors[i] < 1) return true; } diff --git a/test/unit/io/loadModel.js b/test/unit/io/loadModel.js index 0679b6516a..e515af4c22 100644 --- a/test/unit/io/loadModel.js +++ b/test/unit/io/loadModel.js @@ -89,8 +89,8 @@ suite('loadModel', function() { const totalFaces = model.parts.reduce((sum, p) => sum + p.faces.length, 0); assert.equal(totalFaces, model.faces.length); - // first material (m000001) is Kd 0 0 0.5 -> part fill - assert.deepEqual(model.parts[0].partState.fill, [0, 0, 0.5]); + // first material (m000001) is Kd 0 0 0.5 -> part fill, opaque alpha + assert.deepEqual(model.parts[0].partState.fill, [0, 0, 0.5, 1]); assert.equal(model.parts[0].partState.shininess, 100); // faces re-indexed against each part's own localised verts diff --git a/test/unit/io/parseMtl.js b/test/unit/io/parseMtl.js index 5b9c2a158c..c7956ca414 100644 --- a/test/unit/io/parseMtl.js +++ b/test/unit/io/parseMtl.js @@ -60,7 +60,7 @@ suite('mtlToPartState', function() { specularColor: [0, 0, 1], shininess: 32 }); - expect(state.fill).toEqual([1, 0, 0]); + expect(state.fill).toEqual([1, 0, 0, 1]); expect(state.ambientColor).toEqual([0, 1, 0]); expect(state.specularColor).toEqual([0, 0, 1]); expect(state.shininess).toEqual(32); From a5be7752f32086fb193d985183433f176438d6e0 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Tue, 4 Aug 2026 15:15:49 -0400 Subject: [PATCH 4/4] Remove default export addon --- src/webgl/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/webgl/index.js b/src/webgl/index.js index 97281c368a..9bf7a3c353 100644 --- a/src/webgl/index.js +++ b/src/webgl/index.js @@ -8,7 +8,6 @@ import renderBuffer from './p5.RenderBuffer'; import quat from './p5.Quat'; import matrix from '../math/p5.Matrix'; import geometry from './p5.Geometry'; -import geometryPart from './p5.GeometryPart'; import framebuffer from './p5.Framebuffer'; import dataArray from './p5.DataArray'; import camera from './p5.Camera'; @@ -29,7 +28,6 @@ export default function(p5){ p5.registerAddon(quat); p5.registerAddon(matrix); p5.registerAddon(geometry); - p5.registerAddon(geometryPart); p5.registerAddon(camera); p5.registerAddon(framebuffer); p5.registerAddon(dataArray);