p5.js icon indicating copy to clipboard operation
p5.js copied to clipboard

Implement bounding box calculation for p5.Geometry objects

Open Garima3110 opened this issue 1 year ago • 4 comments
trafficstars

Increasing access

The addition of the calculateBoundingBox() method in p5.js enhances accessibility by providing users with an intuitive and standardized method to visualize and analyze the spatial dimensions of 3D objects and will also be helpful in some physics simulations or shape packing. It will simplify complex tasks such as collision detection and camera control, making 3D programming more approachable for a diverse range of users.

Most appropriate sub-area of p5.js?

  • [X] Accessibility
  • [ ] Color
  • [X] Core/Environment/Rendering
  • [ ] Data
  • [ ] DOM
  • [ ] Events
  • [ ] Image
  • [ ] IO
  • [X] Math
  • [ ] Typography
  • [ ] Utilities
  • [X] WebGL
  • [ ] Build process
  • [ ] Unit testing
  • [ ] Internationalization
  • [ ] Friendly errors
  • [ ] Other (specify if possible)

Feature request details

This feature is crucial for users working with 3D graphics, providing an easy and standardized way to determine the spatial extent of objects. Example usage of computeBoundingBox() in a p5.js sketch can be :

let myBox = box(30, 40, 50);
let boundingBox = computeBoundingBox(myBox);
console.log("Bounding Box:", boundingBox);

Garima3110 avatar Feb 03 '24 21:02 Garima3110

I would like to implement this feature.

Garima3110 avatar Feb 03 '24 21:02 Garima3110

I think this could make sense! Some notes on the implementation:

  • Calls like box(30, 40, 50) just draw to the canvas and don't return anything. Instead, could it be a method on p5.Geometry? So your example would instead be:
    const myBox = buildGeometry(() => box(30, 40, 50));
    const boundingBox = myBox.boundingBox();
    
  • Does it always recompute it every time it gets called? Maybe we can cache the result the first time it's accessed, so that we can immediately return it the next time it's asked for? Some models have a lot of vertices in them, so I'm trying to think ahead and make this work as well as possible with those.
  • What data do you expect to be in the box? The contents of the box might be offcenter too, so maybe it needs to have a size property which is a p5.Vector, storing the width/height/depth, and an offset property, another vector with the center of the box?

davepagurek avatar Feb 05 '24 21:02 davepagurek

What data do you expect to be in the box?

In addition to the size and offset properties, I think we would need the max, min properties which too would be instances of the p5.js p5.Vector class.

  • min represents the minimum coordinates of the bounding box along the x, y, and z axes.
  • max represents the maximum coordinates of the bounding box along the x, y, and z axes.

Here's a breakdown:

  • min.x: Smallest x-coordinate of the bounding box.
  • min.y: Smallest y-coordinate of the bounding box.
  • min.z: Smallest z-coordinate of the bounding box.
  • max.x: Largest x-coordinate of the bounding box.
  • max.y: Largest y-coordinate of the bounding box.
  • max.z: Largest z-coordinate of the bounding box.
  • size.x: Width of the bounding box.
  • size.y: Height of the bounding box.
  • size.z: Depth of the bounding box.
  • offset.x: X-coordinate of the center of the bounding box.
  • offset.y: Y-coordinate of the center of the bounding box.
  • offset.z: Z-coordinate of the center of the bounding box.

Garima3110 avatar Feb 08 '24 11:02 Garima3110

Considering your suggestions and that what I have understood, this is what I am upto :

p5.Geometry = class Geometry {
  constructor(detailX, detailY, callback) {
   this.vertices = [];
   this.boundingBoxCache = null;
   }
   
  // Custom bounding box calculation based on the object's vertices
  calculateBoundingBox() {
    if (this.boundingBoxCache) {
      return this.boundingBoxCache; // Return cached result if available
    }

    let minVertex = createVector(
      Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
    let maxVertex = createVector(
      Number.MIN_VALUE, Number.MIN_VALUE, Number.MIN_VALUE);

    for (let i = 0; i < this.vertices.length; i++) {
      let vertex = this.vertices[i];
      minVertex.x = min(minVertex.x, vertex.x);
      minVertex.y = min(minVertex.y, vertex.y);
      minVertex.z = min(minVertex.z, vertex.z);

      maxVertex.x = max(maxVertex.x, vertex.x);
      maxVertex.y = max(maxVertex.y, vertex.y);
      maxVertex.z = max(maxVertex.z, vertex.z);
    }
    
    // Calculate size and offset properties
    let size = createVector(maxVertex.x - minVertex.x,
      maxVertex.y - minVertex.y, maxVertex.z - minVertex.z);
    let offset = createVector((minVertex.x + maxVertex.x) / 2,
      (minVertex.y + maxVertex.y) / 2, (minVertex.z + maxVertex.z) / 2);

    // Cache the result for future access
    this.boundingBoxCache = {
      min: minVertex,
      max: maxVertex,
      size: size,
      offset: offset
    };

    return this.boundingBoxCache;
  }

I would love to have your suggestions on this @davepagurek . Thankyou!

Garima3110 avatar Feb 08 '24 11:02 Garima3110