Skip to content
This repository has been archived by the owner on May 23, 2024. It is now read-only.

Shape Component #90

Merged
merged 10 commits into from
Apr 11, 2018
Merged

Conversation

InfiniteLee
Copy link
Collaborator

Add a shape component that when attached to an entity (or child entity) using a body with shape: none updates the shapes on the CANNON.Body. This enables an easy way to define a body made of multiple primitive shapes, which should be a performant alternative to using convex hulls.

The updating of the body is delayed until tick so that if multiple shape components are defined, the body is only updated once. Does not currently support removing of shapes.

Also updated the wireframe code in body to handle shape offsets and orientations correctly, as well as multiple shapes per body.

…oundShapes" (json blob defining attributes of primitive shapes), that creates a body with those primitives as shapes. Also, update the wireframe code to support this, and fix it to correctly display offsets.
If `type === none` in `body` component, body initialization will be delayed until a `shape` component is added. currently shapes can be added but not removed. debug wireframe updates accordingly.
@wmurphyrd
Copy link
Contributor

+1 for this idea
I frequently need a shape different from what three2cannon will produce (e.g. a box that doesn't expand to include child entities or a box that is just a little thicker than the plane geometry it encloses for easier grabbing), and the current process involves writing a custom component each time to listen for the body loaded event and create the shapes

Copy link
Collaborator

@donmccurdy donmccurdy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition, thanks! 🙂

}
},

addShape(shapeData) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not using ES6 syntax here yet, so this must be:

addShape: function (shapeData) {

}

var type = shapeData.shape;
var scale = this.el.object3D.scale;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get world-space scale:

var scale = new THREE.Vector3();
this.el.object3D.getWorldScale( scale );

orientation.y,
orientation.z,
orientation.w
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think wireframe.quaternion.copy(orientation) should work here, right? unless there was some hitch between the cannonjs and threejs quaternion...

}

if (orientation) {
orientation.inverse(orientation);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a reference to a quaternion still in body.shapeOrientations, so I think we want to make a copy before inverting.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add .clone() where orientation is set.

orientation = this.body.shapeOrientations[i].clone(),

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh nevermind that's a threejs method, not a cannonjs one.

radiusTop: {type: 'number', default: 1},
radiusBottom: {type: 'number', default: 1},
height: {type: 'number', default: 1},
numSegments: {type: 'int', default: 8}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's prefix these properties:

sphereRadius
boxHalfExtents
cylinderRadiusTop
...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer not to- I really like that this exactly matches what those properties are called in threejs. (Selfishly I am also writing some tooling upstream of this that I don't want to have to constantly try to remember what the properties are supposed to be called). I would argue that if we want to be more explicit, we should add the other shape components back in (sphere-shape, box-shape, cylinder-shape)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about adding a updateSchema handler a la geometry that makes the right properties available for the selected shape? That may provide the same clarity of purpose as prefixing

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'm fine with keeping the names then. But even easier than updateSchema, we can do this:

radiusTop: { type: 'number', default: 1, if: {shape: ['cylinder']} }
...

return 'dynamic-body';
} else if (el.components.hasOwnProperty('static-body')) {
return'static-body';
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would do el.hasAttribute('foo-body') here instead

this.bodyEl = this.bodyEl.parentNode;
type = this._findType(this.bodyEl);
}
this.bodyEl.components[type].addShape(this.data);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about having the shape component construct a CANNON.Shape instance and pass that into components.body.addShape( shape )`?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have to think about that one- I vaguely recall I had a reason not to do that, but that might not be the case anymore.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, feels cleaner IMO but if there's some issue we can leave it alone for now.

remove: function() {
if (this.bodyEl.parentNode) {
console.warn('removing shape component not currently supported');
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a case where remove could be called but no parent node exists?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the parent is removed first we don't need to warn about the shape being removed.

InfiniteLee and others added 3 commits April 7, 2018 20:05
…e rotation of cylinder shapes similar to how mesh2shape does it (rotate by 90 degrees). Fix various bugs.
@donmccurdy
Copy link
Collaborator

Nice work, thanks! Will test this out a bit and then cut a new release.

@donmccurdy donmccurdy merged commit a83cb42 into n5ro:master Apr 11, 2018
@donmccurdy
Copy link
Collaborator

Published 3.1.0. 🎊

@jewingo
Copy link

jewingo commented Feb 27, 2019

It looks like compound colliders break when an orientation property is specified (3.3.0) for any component shape; an alternative is using the constraint functionality to create a complex physics body (rotation seems to work fine for primitive body shapes) but I'm worried about overhead with this methodology. Looking into using wmurphyrd's aframe-physics-extras for this

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants