Skip to content

Commit 939d249

Browse files
committed
added texture support for 3D and fixed y-axis for 2D
1 parent ab3e7da commit 939d249

7 files changed

Lines changed: 16014 additions & 83 deletions

File tree

modules/wljs-demos-archive/Demos/Release notes/3.0.3.wln

Lines changed: 15833 additions & 70 deletions
Large diffs are not rendered by default.

modules/wljs-graphics-d3/dist/kernel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2740,7 +2740,7 @@ async function processLabel(ref0, gX, env, textFallback, nodeFallback) {
27402740
const image = await interpretate(args[0], {...env, offscreen: true});
27412741
console.log('got it!');
27422742

2743-
const img = await createImageBitmap(image);
2743+
const img = await createImageBitmap(image, { imageOrientation: 'flipY' });
27442744
image.remove();
27452745

27462746

modules/wljs-graphics-d3/dist/kernel.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/wljs-graphics-d3/src/kernel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2791,7 +2791,7 @@ async function processLabel(ref0, gX, env, textFallback, nodeFallback) {
27912791
const image = await interpretate(args[0], {...env, offscreen: true});
27922792
console.log('got it!');
27932793

2794-
const img = await createImageBitmap(image);
2794+
const img = await createImageBitmap(image, { imageOrientation: 'flipY' });
27952795
image.remove();
27962796

27972797

modules/wljs-graphics3d-threejs/dist/kernel.js

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,8 @@ thickness: env.materialThickness,
11341134
iridescenceThickness: env.iridescenceThickness,
11351135
specularColor: env.specularColor,
11361136
specularIntensity: env.specularIntensity,
1137-
matte: env.matte
1137+
matte: env.matte,
1138+
map: env.texture || null
11381139
});
11391140

11401141
function addSphere(cr) {
@@ -1330,7 +1331,8 @@ g3d.Cube = async (args, env) => {
13301331
iridescenceThickness: env.iridescenceThickness,
13311332
specularColor: env.specularColor,
13321333
specularIntensity: env.specularIntensity,
1333-
matte: env.matte
1334+
matte: env.matte,
1335+
map: env.texture || null
13341336
});
13351337

13361338
const cube = new THREE.Mesh(geometry, material);
@@ -1464,7 +1466,8 @@ thickness: env.materialThickness,
14641466
iridescenceThickness: env.iridescenceThickness,
14651467
specularColor: env.specularColor,
14661468
specularIntensity: env.specularIntensity,
1467-
matte: env.matte
1469+
matte: env.matte,
1470+
map: env.texture || null
14681471

14691472

14701473

@@ -2447,6 +2450,16 @@ g3d.GraphicsComplex = async (args, env) => {
24472450
}
24482451
}
24492452

2453+
if ('VertexTextureCoordinates' in options) {
2454+
const uvData = await interpretate(options["VertexTextureCoordinates"], env);
2455+
2456+
if (uvData instanceof NumericArrayObject) {
2457+
copy.vertices.uv = new THREE.BufferAttribute( new Float32Array( uvData.buffer ), 2 );
2458+
} else {
2459+
copy.vertices.uv = new THREE.BufferAttribute( new Float32Array( uvData.flat() ), 2 );
2460+
}
2461+
}
2462+
24502463
const group = new THREE.Group();
24512464
env.local.group = group;
24522465

@@ -2662,7 +2675,8 @@ thickness: env.materialThickness,
26622675
iridescenceThickness: env.iridescenceThickness,
26632676
specularColor: env.specularColor,
26642677
specularIntensity: env.specularIntensity,
2665-
matte: env.matte
2678+
matte: env.matte,
2679+
map: env.texture || null
26662680
});
26672681

26682682
function addSphere(cr) {
@@ -3060,6 +3074,46 @@ g3dComplex.Polygon = async (args, env) => {
30603074
env.local.geometry.computeVertexNormals();
30613075
}
30623076

3077+
// Apply UV coordinates if available
3078+
if (env?.vertices?.uv) {
3079+
geometry.setAttribute('uv', env.vertices.uv);
3080+
} else if (env.texture) {
3081+
// Auto-generate UVs from vertex positions using planar projection
3082+
const posArray = env.vertices.position.array;
3083+
const count = env.vertices.position.count;
3084+
const uvArray = new Float32Array(count * 2);
3085+
3086+
let minX = Infinity, maxX = -Infinity;
3087+
let minY = Infinity, maxY = -Infinity;
3088+
let minZ = Infinity, maxZ = -Infinity;
3089+
3090+
for (let i = 0; i < count; i++) {
3091+
const x = posArray[i*3], y = posArray[i*3+1], z = posArray[i*3+2];
3092+
if (x < minX) minX = x; if (x > maxX) maxX = x;
3093+
if (y < minY) minY = y; if (y > maxY) maxY = y;
3094+
if (z < minZ) minZ = z; if (z > maxZ) maxZ = z;
3095+
}
3096+
3097+
// Pick the two axes with the largest spread
3098+
const spanX = maxX - minX, spanY = maxY - minY, spanZ = maxZ - minZ;
3099+
let uAxis, vAxis, uMin, vMin, uSpan, vSpan;
3100+
3101+
if (spanX <= spanY && spanX <= spanZ) {
3102+
uAxis = 1; vAxis = 2; uMin = minY; vMin = minZ; uSpan = spanY; vSpan = spanZ;
3103+
} else if (spanY <= spanX && spanY <= spanZ) {
3104+
uAxis = 0; vAxis = 2; uMin = minX; vMin = minZ; uSpan = spanX; vSpan = spanZ;
3105+
} else {
3106+
uAxis = 0; vAxis = 1; uMin = minX; vMin = minY; uSpan = spanX; vSpan = spanY;
3107+
}
3108+
3109+
for (let i = 0; i < count; i++) {
3110+
uvArray[i*2] = uSpan > 0 ? (posArray[i*3 + uAxis] - uMin) / uSpan : 0;
3111+
uvArray[i*2+1] = vSpan > 0 ? (posArray[i*3 + vAxis] - vMin) / vSpan : 0;
3112+
}
3113+
3114+
geometry.setAttribute('uv', new THREE.BufferAttribute(uvArray, 2));
3115+
}
3116+
30633117
//check if colored (Material BUG) !!!
30643118
if (env?.vertices?.colored) {
30653119
//geometry.setAttribute()
@@ -3089,6 +3143,7 @@ thickness: env.materialThickness,
30893143
specularColor: env.specularColor,
30903144
specularIntensity: env.specularIntensity,
30913145
matte: env.matte,
3146+
map: env.texture || null,
30923147
side: THREE.DoubleSide
30933148
});
30943149
} else {
@@ -3116,6 +3171,7 @@ thickness: env.materialThickness,
31163171
specularColor: env.specularColor,
31173172
specularIntensity: env.specularIntensity,
31183173
matte: env.matte,
3174+
map: env.texture || null,
31193175
side: THREE.DoubleSide
31203176
});
31213177
}
@@ -3495,6 +3551,34 @@ g3dComplex.Polygon.destroy = (args, env) => {
34953551

34963552
g3dComplex.Polygon.virtual = true;
34973553

3554+
3555+
/**** Texture for 3D graphics ****/
3556+
3557+
g3d.Texture = async (args, env) => {
3558+
const image = await interpretate(args[0], {...env, offscreen: true});
3559+
3560+
const img = await createImageBitmap(image, { imageOrientation: 'flipY' });
3561+
image.remove();
3562+
3563+
const texture = new THREE.Texture(img);
3564+
texture.colorSpace = THREE.SRGBColorSpace;
3565+
texture.flipY = true;
3566+
texture.needsUpdate = true;
3567+
3568+
env.local.texture = texture;
3569+
env.local.img = img;
3570+
env.exposed.texture = texture;
3571+
};
3572+
3573+
g3d.Texture.destroy = (args, env) => {
3574+
if (env.local.texture) env.local.texture.dispose();
3575+
if (env.local.img) env.local.img.close();
3576+
};
3577+
3578+
g3d.Texture.virtual = true;
3579+
3580+
/********************************/
3581+
34983582
g3d.Polygon = async (args, env) => {
34993583
const vertices = await interpretate(args[0], env);
35003584

modules/wljs-graphics3d-threejs/dist/kernel.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/wljs-graphics3d-threejs/src/kernel.js

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,8 @@ thickness: env.materialThickness,
11211121
iridescenceThickness: env.iridescenceThickness,
11221122
specularColor: env.specularColor,
11231123
specularIntensity: env.specularIntensity,
1124-
matte: env.matte
1124+
matte: env.matte,
1125+
map: env.texture || null
11251126
});
11261127

11271128
function addSphere(cr) {
@@ -1317,7 +1318,8 @@ g3d.Cube = async (args, env) => {
13171318
iridescenceThickness: env.iridescenceThickness,
13181319
specularColor: env.specularColor,
13191320
specularIntensity: env.specularIntensity,
1320-
matte: env.matte
1321+
matte: env.matte,
1322+
map: env.texture || null
13211323
});
13221324

13231325
const cube = new THREE.Mesh(geometry, material);
@@ -1451,7 +1453,8 @@ thickness: env.materialThickness,
14511453
iridescenceThickness: env.iridescenceThickness,
14521454
specularColor: env.specularColor,
14531455
specularIntensity: env.specularIntensity,
1454-
matte: env.matte
1456+
matte: env.matte,
1457+
map: env.texture || null
14551458

14561459

14571460

@@ -2434,6 +2437,16 @@ g3d.GraphicsComplex = async (args, env) => {
24342437
}
24352438
}
24362439

2440+
if ('VertexTextureCoordinates' in options) {
2441+
const uvData = await interpretate(options["VertexTextureCoordinates"], env);
2442+
2443+
if (uvData instanceof NumericArrayObject) {
2444+
copy.vertices.uv = new THREE.BufferAttribute( new Float32Array( uvData.buffer ), 2 );
2445+
} else {
2446+
copy.vertices.uv = new THREE.BufferAttribute( new Float32Array( uvData.flat() ), 2 );
2447+
}
2448+
}
2449+
24372450
const group = new THREE.Group();
24382451
env.local.group = group;
24392452

@@ -2649,7 +2662,8 @@ thickness: env.materialThickness,
26492662
iridescenceThickness: env.iridescenceThickness,
26502663
specularColor: env.specularColor,
26512664
specularIntensity: env.specularIntensity,
2652-
matte: env.matte
2665+
matte: env.matte,
2666+
map: env.texture || null
26532667
});
26542668

26552669
function addSphere(cr) {
@@ -3047,6 +3061,46 @@ g3dComplex.Polygon = async (args, env) => {
30473061
env.local.geometry.computeVertexNormals();
30483062
}
30493063

3064+
// Apply UV coordinates if available
3065+
if (env?.vertices?.uv) {
3066+
geometry.setAttribute('uv', env.vertices.uv);
3067+
} else if (env.texture) {
3068+
// Auto-generate UVs from vertex positions using planar projection
3069+
const posArray = env.vertices.position.array;
3070+
const count = env.vertices.position.count;
3071+
const uvArray = new Float32Array(count * 2);
3072+
3073+
let minX = Infinity, maxX = -Infinity;
3074+
let minY = Infinity, maxY = -Infinity;
3075+
let minZ = Infinity, maxZ = -Infinity;
3076+
3077+
for (let i = 0; i < count; i++) {
3078+
const x = posArray[i*3], y = posArray[i*3+1], z = posArray[i*3+2];
3079+
if (x < minX) minX = x; if (x > maxX) maxX = x;
3080+
if (y < minY) minY = y; if (y > maxY) maxY = y;
3081+
if (z < minZ) minZ = z; if (z > maxZ) maxZ = z;
3082+
}
3083+
3084+
// Pick the two axes with the largest spread
3085+
const spanX = maxX - minX, spanY = maxY - minY, spanZ = maxZ - minZ;
3086+
let uAxis, vAxis, uMin, vMin, uSpan, vSpan;
3087+
3088+
if (spanX <= spanY && spanX <= spanZ) {
3089+
uAxis = 1; vAxis = 2; uMin = minY; vMin = minZ; uSpan = spanY; vSpan = spanZ;
3090+
} else if (spanY <= spanX && spanY <= spanZ) {
3091+
uAxis = 0; vAxis = 2; uMin = minX; vMin = minZ; uSpan = spanX; vSpan = spanZ;
3092+
} else {
3093+
uAxis = 0; vAxis = 1; uMin = minX; vMin = minY; uSpan = spanX; vSpan = spanY;
3094+
}
3095+
3096+
for (let i = 0; i < count; i++) {
3097+
uvArray[i*2] = uSpan > 0 ? (posArray[i*3 + uAxis] - uMin) / uSpan : 0;
3098+
uvArray[i*2+1] = vSpan > 0 ? (posArray[i*3 + vAxis] - vMin) / vSpan : 0;
3099+
}
3100+
3101+
geometry.setAttribute('uv', new THREE.BufferAttribute(uvArray, 2));
3102+
}
3103+
30503104
//check if colored (Material BUG) !!!
30513105
if (env?.vertices?.colored) {
30523106
//geometry.setAttribute()
@@ -3076,6 +3130,7 @@ thickness: env.materialThickness,
30763130
specularColor: env.specularColor,
30773131
specularIntensity: env.specularIntensity,
30783132
matte: env.matte,
3133+
map: env.texture || null,
30793134
side: THREE.DoubleSide
30803135
});
30813136
} else {
@@ -3103,6 +3158,7 @@ thickness: env.materialThickness,
31033158
specularColor: env.specularColor,
31043159
specularIntensity: env.specularIntensity,
31053160
matte: env.matte,
3161+
map: env.texture || null,
31063162
side: THREE.DoubleSide
31073163
});
31083164
}
@@ -3484,6 +3540,34 @@ g3dComplex.Polygon.destroy = (args, env) => {
34843540

34853541
g3dComplex.Polygon.virtual = true;
34863542

3543+
3544+
/**** Texture for 3D graphics ****/
3545+
3546+
g3d.Texture = async (args, env) => {
3547+
const image = await interpretate(args[0], {...env, offscreen: true});
3548+
3549+
const img = await createImageBitmap(image, { imageOrientation: 'flipY' });
3550+
image.remove();
3551+
3552+
const texture = new THREE.Texture(img);
3553+
texture.colorSpace = THREE.SRGBColorSpace;
3554+
texture.flipY = true;
3555+
texture.needsUpdate = true;
3556+
3557+
env.local.texture = texture;
3558+
env.local.img = img;
3559+
env.exposed.texture = texture;
3560+
}
3561+
3562+
g3d.Texture.destroy = (args, env) => {
3563+
if (env.local.texture) env.local.texture.dispose();
3564+
if (env.local.img) env.local.img.close();
3565+
}
3566+
3567+
g3d.Texture.virtual = true
3568+
3569+
/********************************/
3570+
34873571
g3d.Polygon = async (args, env) => {
34883572
const vertices = await interpretate(args[0], env);
34893573

0 commit comments

Comments
 (0)