How to manually define vertices in box2D javascript? - javascript

I am trying to manually define the vertices of a polygon in box2D for javascript. I ultimately want to resize each side of a box manually, but I need to be able to draw it with vertices first (I already have a resizing mechanism). I've looked at the examples in the manual, but they are for ActionScript, and it doesn't seem to work in javascript. I've tried defining the polygon in different ways (like standalone polygon = new b2Polygon;), but it makes no difference.
No matter how I define a new polygon, the box2D source is throwing an error in the call to create the fixture. The error says "tVec is undefined," which is a variable in the box2D function: b2PolygonShape.prototype.ComputeAABB = function (aabb, xf)
Here are the relevant parts of the code(fixDef and bodyDef are created earlier in the code):
var vertices = [];
vertices[0] = new b2Vec2()
vertices[0].Set(1,1);
vertices[1] = new b2Vec2();
vertices[1].Set(1, 6);
vertices[2] = new b2Vec2();
vertices[2].Set(6, 6);
vertices[3] = new b2Vec2();
vertices[3].Set(6, 1);
fixDef.shape = new b2PolygonShape;
fixDef.shape.Set(vertices, 4);
world.CreateBody(bodyDef).CreateFixture(fixDef);
Any help would be greatly appreciated as this has been giving me trouble for a while now.

Related

Programatically create skeleton in Three.js

I am loading a model of a mechanism (e.g. a robot arm) in Three.js. Sadly the models I am using don't have a skeleton, but I have the locations, axes and so on of the joints. In order to use e.g. inverse kinematic solvers like Three-IK, I want to create a skeleton from these parameters. Since I want to use many different models I would prefer to not create the skeletons by hand but in code.
I have been trying for over a week now to create a valid bone structure from these values that reflects the model, but nothing succeeded. For example, if I create a chain of bones using the positions of the joints I get a very long skeleton which in no way matches the positions I used.
let boneParent;
let bonepos = [];
let bones = [];
model.traverse(child => {
switch(child.type) {
case "joint":
let p = new Vector3();
child.getWorldPosition(p);
bonepos.push(p);
let bone = new Bone();
boneParent && boneParent.add(p);
bone.worldToLocal(p.clone());
bone.position.copy(p);
bone.rotation.copy(child.rotation);
bone.scale.copy(child.scale);
boneParent = bone;
bones.push(bone);
break;
}
});
showPoints(scene, bonepos, 0xff0000);
const skeletonHelper = new SkeletonHelper(bones[0]);
skeletonHelper.visible = true;
scene.add(skeletonHelper);
The code above results in the screenshot below. The red markers are the positions I get from the robot joints, the line snaking into the distance is the skeleton as visualized by the SkeletonHelper.
So my question is this: it seems like I don't understand well enough how bones are handled in Three.js. How can I create a skeleton that reflects my existing model from its joint locations and orientations?
Thanks in advance!
child.getWorldPosition(p);
I'm afraid it's incorrect to apply the position in world space to Bone.position which represents the position in local space.
boneParent = bone;
This line looks problematic, too. A bone can have multiple child elements. It seems to me that this use case is not considered of your code.
After some fiddling around I found a solution:
let root = new Bone();
let parent = root;
let pos = new Vector3();
for (let joint of robot.arm.movable) {
let link = robot.getLinkForJoint(joint);
link.getWorldPosition(pos);
let bone = new Bone();
parent.add(bone);
parent.lookAt(pos);
parent.updateMatrixWorld(); // crucial for worldToLocal!
bone.position.copy(bone.worldToLocal(pos));
parent = bone;
}
The important part is to call updateMatrixWOrld() after lookAt() so that bone.worldToLocal() works correctly. Also lookAt() saves a lot of matrix hassles :)

How to get the bounds of a PIXI.Graphics instance using pixi.js?

I'm trying to get the bounding box of a Graphics instance with the world transformation applied using pixi.js
I'm a bit confused using the PIXI.Graphics documentation.
As far as I can understand, it should inherit width, height, calculateBounds(), getBounds(), etc.
However when I create a PIXI.Graphics instance, these properties seem to be missing:
var g = new PIXI.Graphics();
g.beginFill(0xFF9900);
g.drawRect(-50,-50,100,100);
g.endFill();
g.position.x = g.position.y = 300;
stage.addChild(g);
g.getBounds();
//throws
//VM847:1 Uncaught TypeError: g.getBounds is not a function
// at <anonymous>:1:3
What's the simplest way to calculate the transformed bounding box of a Graphics object using pixi.js ?
Works for me.
https://repl.it/#CurlyBrace/PixiBounds
The problem is probably in the version you are using. Are you sure its the last one? For example there is outdated package named "pixi".

Change color of shape without recreating

I have a project using easelJS in that I'm trying to simply change the color of a shape object. I have a couple of examples but they both seem to indicate I would need to completely redraw the shape with a graphics.beginFill() call again. This seems completely overkill considering that I've stored my shape object already and am able to perform other manipulations on it.
I've also tried to use ColorFilter and ColorMatrix but have not had luck making a clean color change. In some cases the color essentially "overwrites" the detail of the shape.
I have an array of ShapeObject that I store the createjs.Shape() object in.
var ShapeObject = function()
{
this.name;
this.shape;
this.rotation;
this.color;
};
sObject = new ShapeObject();
myShape = new createjs.Shape();
sObject.shape = myShape;
shapes = new Array();
shapes.push(sObject);
Later I am able to retrieve the shape from the array and apply a filter, for example,
s = shapes[i];
filter = new createjs.ColorFilter(0,0,0,1, 255,128,0,0);
s.shape.filters = [ filter ];
Using this same example I'd like to avoid having to completely recreate the shape. I have tried the following but, while it changes color, I lose all the other details of the shape that was originally applied.
s.shape.graphics.clear().beginFill(color);
Does anyone have an idea of how to simply change the color without completely recreating the original shape?
EDIT
Following the answer regarding .command and the createjs command blog post I have created the following.
var theShape = new createjs.Shape();
var fillCommand = theShape.graphics.beginFill("yellow").command;
theShape.graphics.setStrokeStyle(1)
.beginStroke(createjs.Graphics.getRGB(0, 0, 0))
.drawCircle(0, 0, 20)
.moveTo(0,-20)
.lineTo(0,0)
.moveTo(0,0)
.lineTo(20,0);
fillCommand.style = "orange";
Despite being nearly identical to the examples I am receiving the error Uncaught TypeError: Cannot set property 'style' of undefined at the last line above.
I wouldn't use ColorFilter or ColorMatrix, it will likely be much slower. But you could use the Graphics command object, check out the docs: http://www.createjs.com/docs/easeljs/classes/Graphics.html
var fillCommand = myGraphics.beginFill("red").command;
// ... later, update the fill style/color:
fillCommand.style = "blue";

Raycaster does not move BoxMesh objects

I'm using Physijs script for physics like gravitation.
I want to move objects in my scene with Raycaster from THREE.js script.
My problem is that Raycaster only move objects (simple box) declared like:
var box = new Physijs.Mesh(cubeGeomtery.clone(), createMaterial);
But here physics does not work. It only works if I declare it like:
var create = new Physijs.BoxMesh(cubeGeomtery.clone(), createMaterial);
But here Raycaster / moving does not work.
The difference between these two is that in the first it's just Mesh and in the second it's BoxMesh.
Does anyone know why this doesn't work? I need BoxMesh in order to use gravity and other physics.
Code to add cube
function addCube()
{
controls.enable = false;
var cubeGeomtery = new THREE.CubeGeometry(85, 85, 85);
var createTexture = new THREE.ImageUtils.loadTexture("images/rocks.jpg");
var createMaterial = new THREE.MeshBasicMaterial({ map: createTexture });
var box = new Physijs.BoxMesh(cubeGeomtery.clone(), createMaterial);
box.castShadow = true;
box.receiveShadow = true;
box.position.set(0, 300, 0);
objects.push(box);
scene.add(box);
}
Explanation
In Physijs, all primitive shapes (such as the Physijs.BoxMesh) inherit from Physijs.Mesh, which in turn inherits from THREE.Mesh. In the Physijs.Mesh constructor, there is a small internal object: the ._physijs field. And, in that object, there is... a shape type declaration, set to null by default. That field must be re-assigned by one of its children. If not, when the shape is passed to the scene, the Physijs worker script won't know what kind of shape to generate and simply abort. Since the Physijs.Scene inherits from the THREE.Scene, the scene keeps a reference of the mesh internally like it should, which means that all methods from THREE.js will work (raycasting, for instance). However, it is never registered as a physical object because it has no type!
Now, when you are trying to move the Physijs.BoxMesh directly with its position and rotation fields, it is immediately overridden by the physics updates, which started with the .simulate method in your scene object. When called, it delegates to the worker to compute new positions and rotations that correspond to the physics configurations in your scene. Once it's finished, the new values are transferred back to the main thread and updated automatically so that you don't have to do anything. This can be a problem in some cases (like this one!). Fortunately, the developer included 2 special fields in Physijs.Mesh: the .__dirtyPosition and .__dirtyRotation flags. Here's how you use them:
// Place box already in scene somewhere else
box.position.set(10, 10, 10);
// Set .__dirtyPosition to true to override physics update
box.__dirtyPosition = true;
// Rotate box ourselves
box.rotation.set(0, Math.PI, 0);
box.__dirtyRotation = true;
The flags get reset to false after updating the scene again via the .simulate method.
Conclusion
It is basically useless to create a Physijs.Mesh yourself, use one of the primitives provided instead. It is just a wrapper for THREE.Mesh for Physijs and has no physical properties until modified properly by one of its children.
Also, when using a Physijs mesh, always set either the .__dirtyPosition or the .__dirtyRotation property in the object to directly modify position or rotation, respectively. Take a look in the above code snippet and here.

Inverse of camera.lookAt()

I googled far and wide but I haven't found the solution to what I think to actually be a pretty common situation. Say I have a THREE.PerspectiveCamera initialized to look at a certain point in space:
var camera = new THREE.PerspectiveCamera(45, 2, 0.1, 100);
var target = new THREE.Vector3(1, 2, 3);
camera.lookAt(target);
Now, later on in the code I'd like to be able to find out the coordinates of target by simply querying camera.
I tried what suggested in this question, adapting it to my own scenario:
var vector = new THREE.Vector3();
vector.applyQuaternion(camera.quaternion);
console.log(vector);
But it logs a vector of coordinates (0, 0, 0) instead of the correct coordinates (which, in my example, should be (1, 2, 3)).
Any insights? Cheers.
EDIT:
Ok so I'm going to try to contextualize here, so as to justify why MrTrustworthy's solution is unfortunately not applicable in my scenario. I'm trying to tweak the THREE.OrbitControls library for my purposes, since I noticed that when using it, it overrides whichever position the camera was looking at originally. This has also been reported here. Basically, on line 36 of OrbitControls.js (I'm using the version which can be found here) this.target is initialized to a new THREE.Vector3(); I found out that if I manually set it to equal the same vector I use as argument of camera.lookAt() everything works just fine: I can start panning, orbiting and zooming the scene from the same POV I would see the scene from if I didn't apply the controls. Of course, I cannot hard-code this information into OrbitControls.js because it would require me to change it every time I want to change the initial "lookAt" of my camera; and if I were to follow MrTrustworthy's suggestion I would have to change line 36 of OrbitControls.js to read like this: this.target = object.targetRef (or this.target = object.targetRef || new THREE.Vecotr3()), which is also too "opinionated" (it would always require object to have a targetRef property, whereas I'm trying to stick to using only three.js's existing object properties and methods). Hope this helps get a better understanding of my case. Cheers.
If your only usecase is "I want to be able to access the camera-targets position via the camera object", you could just put a reference into the camera object.
var camera = new THREE.PerspectiveCamera(45, 2, 0.1, 100);
var target = new THREE.Vector3(1, 2, 3);
camera.lookAt(target);
camera.targetRef = target;
//access it
var iNeedThisNow = camera.targetRef;
I figured it out and wrote my solution here. Since the issue affects both THREE.TrackballControls and THREE.OrbitControls, the solution involves applying a slight change to both those files. I wonder if it can be considered a valid change and make its way to rev. 70; I will issue a PR on github just for the sake of it :)
Thanks to all those who pitched in.
well you could put the object in parent, have parent lookat, and have the child object rotated 180 degrees. That's the quick noob solution

Categories

Resources