I am fairly new to cocos 2d and chipmunk. So far i have managed to create a static object and add collision handler to it. But i want to create a dynamic.
this.space = space;
this.sprite = new cc.PhysicsSprite("#rock.png");
var body = new cp.StaticBody();
body.setPos(pos);
this.sprite.setBody(body);
this.shape = new cp.BoxShape(body,
this.sprite.getContentSize().width,
this.sprite.getContentSize().height);
this.shape.setCollisionType(SpriteTag.rock);
this.space.addStaticShape(this.shape);
spriteSheet.addChild(this.sprite);
But i want to create a dynamic body similarly which moves for example by:
cp.v(310, 0), cp.v(0, 0)
This is very basic I know but I would grateful if someone would help me with this. Also if you have good documentation in of cocos 2d and chipmunk in JS. do share it. Thanks
Here you go:
//Add the Chipmunk Physics space
var space = new cp.Space();
space.gravity = cp.v(0, -10);
//Optionally add the debug layer that shows the shapes in the space moving:
/*var debugNode = new cc.PhysicsDebugNode(space);
debugNode.visible = true;
this.addChild(debugNode);*/
//add a floor:
var floor = new cp.SegmentShape(this.space.staticBody, cp.v(-1000, 10), cp.v(1000, 0), 10);
//floor.setElasticity(1);
//floor.setFriction(0);
space.addStaticShape(floor);
//add a square to bounce
//the Sprite
var mySprite = cc.PhysicsSprite.create("res/something.png");
gameLayer.addChild(mySprite);
//the Body
var size = mySprite.getContentSize();
var innertialMomentum = 1; //Use Infinity if you want to avoid the body from rotating
var myBody = new cp.Body(innertialMomentum , cp.momentForBox(innertialMomentum , size.width, size.height));
mySprite.setBody(myBody);
space.addBody(myBody);
//myBody.p = cc.p(xxx, yyy); //To alter the position of the sprite you have to manipulate the body directly, otherwise it won't have the desired effect. You can also access it by mySprite.body
//the Shape
var myShape = new cp.BoxShape(myBody, size.width, size.height);
//myShape.setElasticity(1);
//myShape.setFriction(0);
space.addShape(myShape);
//Apply your desired impulse
//mySprite.body.applyImpulse(cp.v(ix,iy), cp.v(rx,ry)); // Where the first vector is for the impulse strength and direction and the second is for the offset between the center of the object and where you want the impulse to be applied.
Related
I have been working with leaflet-editable.js to allow the editing of shapes. Specifically I am creating a rectangle that will maintain an aspect ratio of 4:3 when a corner is dragged. I have created a function to calculate the aspect ratio and return the lat/lng of where the new corners should be drawn.
I have attached this function to the event "editable:vertex:drag".
I'm not sure how to update the actual drawing of the rectangle to keep the scale. I have tried setting the object properties to the new bounds which updates but doesn't change the rectangle.
I think the answer is in refreshing the drawing of the rectangle but I don't know how to get the current rectangle instance nor how to refresh it.
Javascript is new for me
carto.on('editable:vertex:drag', function(e) {
console.log(e);
var cornersNe = e.vertex.latlngs[0], //ne
cornersNw = e.vertex.latlngs[1], //nw
cornersSw = e.vertex.latlngs[2], //sw
cornersSe = e.vertex.latlngs[3]; //se
var distanceWidth = carto.distance(cornersNw, cornersNe).toFixed(2);
var distanceHeight = carto.distance(cornersSw, cornersNw).toFixed(2);
var asR = aspectRatio(distanceWidth, distanceHeight, e.latlng.lat, e.latlng.lng);
var index = e.vertex.getIndex(),
next = e.vertex.getNext(),
previous = e.vertex.getPrevious(),
oppositeIndex = (index + 2) % 4,
opposite = e.vertex.latlngs[oppositeIndex],
bounds = new L.LatLngBounds(asR, opposite);
// L.marker(bounds).addTo(carto);
console.log('first set of bounds ', e.layer._bounds);
console.log('bounds to set ', bounds);
e.layer._bounds = bounds;
console.log('Updated set ',e.layer._bounds);
I am open to other ways of doing it if this is too roundabout.
Use the public function to set the bounds:
e.layer.setBounds(bounds);
I'm having a three.js object in my scene, which you can rotate/scale/move with the THREE.TransformControls. After positioning the object in the scene, the values of rotation/position/scale should be saved. I'm getting the values like this :
// Position
$scope.scene.updateMatrixWorld(true);
var position = new THREE.Vector3();
position.getPositionFromMatrix( $scope.object.matrixWorld );
// Rotation
var rotation = new THREE.Euler();
$scope.object.getWorldRotation(rotation);
// Size
var size = new THREE.Box3().setFromObject($scope.object);
var x = (size.max.x - size.min.x);
var y = (size.max.y - size.min.y);
var z = (size.max.z - size.min.z);
So, when I'm saving the values and reload the scene with the new values, the object looks really different than it should. So, I think, the functions deliver the wrong values for rotation/scale/position. For example, the size.z variable should always be 0, but when saving (and printing the value in the console) it gets an other value.
Does anyone have an idea why ?
Thanks for helping.
Three.js offers a matrix decomposition function: https://threejs.org/docs/#api/math/Matrix4.decompose
Here's an example of how to use it:
var translation = new THREE.Vector3();
var rotationQ = new THREE.Quaternion();
var scale = new THREE.Vector3();
myObject.matrixWorld.decompose(translation, rotationQ, scale);
Then if you want to save the rotation as an Euler:
var rotationE = new THREE.Euler().setFromQuaternion(rotationQ.normalize());
three.js r88
I need to fill a rectangle with an image. I've tried Raster but I am not able to figure out how to use raster inside the rectangle created on the canvas.
Is there a function similar to fillColor() method for filling the rectangle with an image rather than colors?
Any hints/tips or a sample fiddle would be great!
Here is what you can do:
// Create your raster:
var url = 'http://assets.paperjs.org/images/marilyn.jpg';
var raster = new Raster(url);
raster.position = new Point(300,300);
// Use clipMask to create a custom polygon clip mask:
var path = new Path.Rectangle(150,150,100,150);
path.clipMask = true;
// It is better to add the path and the raster in a group (but not mandatory)
/*
var group = new Group();
group.addChild(raster);
group.addChild(path);
*/
// If you just need a rectangle part of a raster, you could use getSubRaster(rect) instead:
/*
var subRaster = raster.getSubRaster(new Rectangle(150,150,100,150));
subRaster.position = new Point(600,600);
*/
I get the current bounds of a google map by calling:
map.getBounds()
This will return LatLngBounds. For example:
((-26.574013562724005, -1.5375947819336488), (-25.230016040794602, 3.735842718066351))
Is it possible to get the the new LatLng points if I want to increase the map bounds by a percentage (e.g. 1%) around the centre of the map.
I have tried multiplying every coordinate by 1.01 but this shifts the map and does not increase the bounds.
I want to use the increased box size to start caching markers, in order to save calls to the server when the user pans or zooms out.
The image below will explain better what needs to happen:
Based on markerclusterer getExtendedBounds function you could use this one:
function getExtendedBounds(map, overlay) {
//With _mapBoundsEnlargePixels we add some extra space surrounding the map
//change this value until you get the desired size
var _mapBoundsEnlargePixels = 500;
var projection = overlay.getProjection();
var bounds = angular.copy(map.getBounds());
// Turn the bounds into latlng.
var tr = new google.maps.LatLng(bounds.getNorthEast().lat(),
bounds.getNorthEast().lng());
var bl = new google.maps.LatLng(bounds.getSouthWest().lat(),
bounds.getSouthWest().lng());
// Convert the points to pixels and extend out
var trPix = projection.fromLatLngToDivPixel(tr);
trPix.x = trPix.x + _mapBoundsEnlargePixels;
trPix.y = trPix.y - _mapBoundsEnlargePixels;
var blPix = projection.fromLatLngToDivPixel(bl);
blPix.x = blPix.x - _mapBoundsEnlargePixels;
blPix.y = blPix.y + _mapBoundsEnlargePixels;
// Convert the pixel points back to LatLng
var ne = projection.fromDivPixelToLatLng(trPix);
var sw = projection.fromDivPixelToLatLng(blPix);
// Extend the bounds to contain the new bounds.
bounds.extend(ne);
bounds.extend(sw);
return bounds;
}
How do I get the world rotation of an Object3D in three.js?
I know how to get the world position of an Object3D from object.matrixWorld, but how do I get the world rotation of an object?
I need this for the following problem: I have a hierarchical Object structure like this:
var obj1 = new THREE.Object3D();
obj1.x = 200;
obj1.rotation.x = 0.1;
scene.add(obj1);
var obj2 = new THREE.Object3D();
obj2.y = -400;
obj2.rotation.y = 0.21;
obj1.add(obj2);
var obj3 = new THREE.Object3D();
obj3.z = -200;
obj3.rotation.x = 0.1;
obj3.rotation.y = -0.1;
obj2.add(obj3);
Now I want to make my camera look at obj3 orthogonally in a certain distance. When My Objects are not rotated, this works like this:
var relativeCameraOffset = new THREE.Vector3(0, 0, 500); // 500 is z-distance from my object
var cameraOffset = relativeCameraOffset.applyMatrix4(obj3.matrixWorld);
camera.position = cameraOffset;
When only my last child is rotated I get what I want when I add this line
camera.rotation = obj3.rotation;
But when all parent Elements are rotated this is not working. So I'm looking for a way to get the world "orientation" of my 3D object.
Thanks.
One way to get the "world" rotation is as follows:
const position = new THREE.Vector3(); // create one and reuse it
const quaternion = new THREE.Quaternion();
const scale = new THREE.Vector3();
mesh.matrixWorld.decompose( position, quaternion, scale );
You can then set your camera orientation like so:
camera.quaternion.copy( quaternion );
Important: if you are going to access matrixWorld directly, you have to make sure it is updated. The renderer typically does this for you in the render loop. If, however, you are between render calls, and need to force an update of the matrix, you can do so with
mesh.updateWorldMatrix( true, false );
EDIT: There is another method that is now available. Check the source code so you see what it is doing.
Object3D.getWorldQuaternion( targetQuaternion );
three.js r.147
If you just want to link camera with obj3, you can just do this:
obj3.add(camera);
Use mesh.getWorldPosition() to get world position, and mesh.getWorldRotation() to get it's rotation.