@@ -1146,6 +1146,154 @@ function exitFullscreen() {
1146
1146
}
1147
1147
}
1148
1148
1149
+
1150
+ /**
1151
+ * Converts 3D world coordinates to 2D screen coordinates.
1152
+ *
1153
+ * This function takes a 3D vector and converts its coordinates
1154
+ * from the world space to screen space. This can be useful for placing
1155
+ * 2D elements in a 3D scene or for determining the screen position
1156
+ * of 3D objects.
1157
+ *
1158
+ * @method worldToScreen
1159
+ * @param {p5.Vector } worldPosition The 3D coordinates in the world space.
1160
+ * @return {p5.Vector } A vector containing the 2D screen coordinates.
1161
+ * @example
1162
+ * <div>
1163
+ * <code>
1164
+ *
1165
+ * function setup() {
1166
+ * createCanvas(150, 150);
1167
+ * let vertices = [
1168
+ * createVector(-20, -20),
1169
+ * createVector(20, -20),
1170
+ * createVector(20, 20),
1171
+ * createVector(-20, 20)
1172
+ * ];
1173
+ *
1174
+ * push();
1175
+ * translate(75, 55);
1176
+ * rotate(PI / 4);
1177
+ *
1178
+ * // Convert world coordinates to screen coordinates
1179
+ * let screenPos = vertices.map(v => worldToScreen(v));
1180
+ * pop();
1181
+ *
1182
+ * background(200);
1183
+ *
1184
+ * stroke(0);
1185
+ * fill(100, 150, 255, 100);
1186
+ * beginShape();
1187
+ * screenPos.forEach(pos => vertex(pos.x, pos.y));
1188
+ * endShape(CLOSE);
1189
+ *
1190
+ * screenPos.forEach((pos, i) => {
1191
+ * fill(0);
1192
+ * textSize(10);
1193
+ * if (i === 0) {
1194
+ * text(i + 1, pos.x + 3, pos.y - 7);
1195
+ * } else if (i === 1) {
1196
+ * text(i + 1, pos.x + 7, pos.y + 2);
1197
+ * } else if (i === 2) {
1198
+ * text(i + 1, pos.x - 2, pos.y + 12);
1199
+ * } else if (i === 3) {
1200
+ * text(i + 1, pos.x - 12, pos.y - 2);
1201
+ * }
1202
+ * });
1203
+ *
1204
+ * fill(0);
1205
+ * noStroke();
1206
+ * textSize(10);
1207
+ * let legendY = height - 35;
1208
+ * screenPos.forEach((pos, i) => {
1209
+ * text(`Vertex ${i + 1}: (${pos.x.toFixed(1)}, ${pos.y.toFixed(1)})`, 5, legendY + i * 10);
1210
+ * });
1211
+ *
1212
+ * describe('A rotating square is transformed and drawn using screen coordinates.');
1213
+ *
1214
+ * }
1215
+ * </code>
1216
+ * </div>
1217
+ *
1218
+ * @example
1219
+ * <div>
1220
+ * <code>
1221
+ * let vertices;
1222
+ *
1223
+ * function setup() {
1224
+ * createCanvas(100, 100, WEBGL);
1225
+ * vertices = [
1226
+ * createVector(-25, -25, -25),
1227
+ * createVector(25, -25, -25),
1228
+ * createVector(25, 25, -25),
1229
+ * createVector(-25, 25, -25),
1230
+ * createVector(-25, -25, 25),
1231
+ * createVector(25, -25, 25),
1232
+ * createVector(25, 25, 25),
1233
+ * createVector(-25, 25, 25)
1234
+ * ];
1235
+ *
1236
+ * describe('A rotating cube with points mapped to 2D screen space and displayed as ellipses.');
1237
+ *
1238
+ * }
1239
+ *
1240
+ * function draw() {
1241
+ * background(200);
1242
+ *
1243
+ * // Animate rotation
1244
+ * let rotationX = millis() / 1000;
1245
+ * let rotationY = millis() / 1200;
1246
+ *
1247
+ * push();
1248
+ *
1249
+ * rotateX(rotationX);
1250
+ * rotateY(rotationY);
1251
+ *
1252
+ * // Convert world coordinates to screen coordinates
1253
+ * let screenPos = vertices.map(v => worldToScreen(v));
1254
+ *
1255
+ * pop();
1256
+ *
1257
+ * screenPos.forEach((pos, i) => {
1258
+ *
1259
+ * let screenX = pos.x - width / 2;
1260
+ * let screenY = pos.y - height / 2;
1261
+ * fill(0);
1262
+ * noStroke();
1263
+ * ellipse(screenX, screenY, 3, 3);
1264
+ * });
1265
+ * }
1266
+ * </code>
1267
+ * </div>
1268
+ *
1269
+ */
1270
+
1271
+ p5 . prototype . worldToScreen = function ( worldPosition ) {
1272
+ const renderer = this . _renderer ;
1273
+ if ( renderer . drawingContext instanceof CanvasRenderingContext2D ) {
1274
+ // Handle 2D context
1275
+ const transformMatrix = new DOMMatrix ( )
1276
+ . scale ( 1 / renderer . _pInst . pixelDensity ( ) )
1277
+ . multiply ( renderer . drawingContext . getTransform ( ) ) ;
1278
+ const screenCoordinates = transformMatrix . transformPoint (
1279
+ new DOMPoint ( worldPosition . x , worldPosition . y )
1280
+ ) ;
1281
+ return new p5 . Vector ( screenCoordinates . x , screenCoordinates . y ) ;
1282
+ } else {
1283
+ // Handle WebGL context (3D)
1284
+ const modelViewMatrix = renderer . calculateCombinedMatrix ( ) ;
1285
+ const cameraCoordinates = modelViewMatrix . multiplyPoint ( worldPosition ) ;
1286
+ const normalizedDeviceCoordinates =
1287
+ renderer . states . uPMatrix . multiplyAndNormalizePoint ( cameraCoordinates ) ;
1288
+ const screenX = ( 0.5 + 0.5 * normalizedDeviceCoordinates . x ) * this . width ;
1289
+ const screenY = ( 0.5 - 0.5 * normalizedDeviceCoordinates . y ) * this . height ;
1290
+ const screenZ = 0.5 + 0.5 * normalizedDeviceCoordinates . z ;
1291
+ return new p5 . Vector ( screenX , screenY , screenZ ) ;
1292
+ }
1293
+ } ;
1294
+
1295
+
1296
+
1149
1297
/**
1150
1298
* Returns the sketch's current
1151
1299
* <a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL" target="_blank">URL</a>
0 commit comments