Adding a second fixture as sensor to body in Box2Dweb - box2dweb

I have two problems adding a sensor fixture in the following code. The repositioning vector b2Vec2(0,50) is not working; the second fixture is still centered at the origin of the body. Both fixtures can be seen in debug mode but I can't move the sensor fixture to the foot of the main fixture.
Secondly, when isSensor is true I am not receiving any PostSolve events. When it is set to false I get the appropriate events (along with collision). How do I make this a sensor that will not collide with other bodies but still raise events. Thank you for your help.
// FIXTURE DEF
var fixDef = new box2d.b2FixtureDef();
fixDef.shape = new box2d.b2PolygonShape;
fixDef.shape.SetAsBox((25 / 2 / SCALE), (46 / 2 / SCALE));
fixDef.density = 0.99;
fixDef.friction = 0.39;
fixDef.restitution = 0.0;
fixDef.userData = "SBody";
fixDef.filter.categoryBits = CAT.SOLDIER;
fixDef.filter.maskBits = CAT.GROUND;
this.view.body.CreateFixture(fixDef);
// ADD FOOT SENSOR
fixDef.density = 0.1;
fixDef.friction = 1.;
fixDef.restitution = 0.1;
fixDef.userData = "Foot";
fixDef.shape.SetAsBox((10 / 2 / SCALE), (100 / 2 / SCALE), new box2d.b2Vec2(0,50), 0);
fixDef.isSensor = true;
fixDef.filter.categoryBits = CAT.SOLDIER_FOOT_SENSOR;
fixDef.filter.maskBits = CAT.SHIP | CAT.GROUND;
this.view.body.CreateFixture(fixDef);

I was using the tip in this answer https://stackoverflow.com/a/4707127/1172891 that said to add positioning as the 3rd parameter, but I recently found that SetAsBox cannot take a 3rd argument, maybe it used to. Instead I found SetAsOrientedBox is a similar method and accepts the 3rd parameter for positioning. Found on the Box2dFlash reference http://www.box2dflash.org/docs/2.1a/reference/Box2D/Collision/Shapes/b2PolygonShape.html
For the sensor callbacks, I was only trying the PostSolve at first. I recently thought to try the other events like EndContact and found that it worked. I then found this page that seems to be the only place that explicitly states that sensors only raise BeginContact and EndContact events: http://www.box2dflash.org/docs/2.1a/updating in the Events section.
Hope that saves someone some time!

Related

No output in second RenderTarget when blend state is set

I have a strange issue when using two RenderTargets in SharpDX, using DX11.
I am rendering a set of objects that can be layered, and am using blend modes to achieve partial transparency. Rendering is done to two render targets in a single pass, with the second render target being used as a colour picker - I simply render the object ID (integer) to this second target and retrieve the object ID from the texture under the mouse after rendering.
The issue I am getting is frustrating, as it does not happen on all computers. In fact, it doesn't happen on any of our development machines but has been reported in the wild - typically on machines with integrated Intel (HD) graphics. On these computers, no output is generated in the second render target. We have been able to reproduce the problem on a laptop here, and if we don't set the blend state, then the issue is resolved. Obviously this isn't a fix, since we need the blending.
The texture descriptions for the main render target (0) and the colour picking target look like this:
var desc = new Texture2DDescription
{
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
Format = Format.B8G8R8A8_UNorm,
Width = width,
Height = height,
MipLevels = 1,
SampleDescription = sampleDesc,
Usage = ResourceUsage.Default,
OptionFlags = RenderTargetOptionFlags,
CpuAccessFlags = CpuAccessFlags.None,
ArraySize = 1
};
var colourPickerDesc = new Texture2DDescription
{
BindFlags = BindFlags.RenderTarget,
Format = Format.R32_SInt,
Width = width,
Height = height,
MipLevels = 1,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
OptionFlags = ResourceOptionFlags.None,
CpuAccessFlags = CpuAccessFlags.None,
ArraySize = 1,
};
The blend state is set like this:
var blendStateDescription = new BlendStateDescription { AlphaToCoverageEnable = false };
blendStateDescription.RenderTarget[0].IsBlendEnabled = true;
blendStateDescription.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha;
blendStateDescription.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha;
blendStateDescription.RenderTarget[0].BlendOperation = BlendOperation.Add;
blendStateDescription.RenderTarget[0].SourceAlphaBlend = BlendOption.SourceAlpha;
blendStateDescription.RenderTarget[0].DestinationAlphaBlend = BlendOption.InverseSourceAlpha;
blendStateDescription.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add;
blendStateDescription.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;
_blendState = new BlendState(_device, blendStateDescription);
and is applied at the start of rendering. I have tried explicitly setting IsBlendEnabled to false for RenderTarget[1] but it makes no difference.
Any help on this would be most welcome - ultimately, we may have to resort to making two render passes but that would be annoying.
I have now resolved this issue, although exactly how or why the "fix" works in not entirely clear. Hat-tip to VTT for pointing me to the IndependentBlendEnable flag in the BlendStateDescription. Setting that flag on its own (to true), along with RenderTarget[1].IsBlendEnabled = false, was not enough. What worked in the end was filling a complete set of values for RenderTarget[1], along with the aforementioned flags. Presumably all other values in the second RenderTarget would be ignored, as blend is disabled, but for some reason they need to be populated. As mentioned before, this problem only appears on certain graphics cards so I have no idea if this is the correct behaviour or just a quirk of those cards.

Box2D: How to use b2ChainShape for a tile based map with squares

Im fighting here with the so called ghost collisions on a simple tile based map with a circle as player character.
When applying an impulse to the circle it first starts bouncing correctly, then sooner or later it bounces wrong (wrong angle).
Looking up on the internet i read about an issue in Box2D (i use iOS Swift with Box2d port for Swift).
Using b2ChainShape does not help, but it looks i misunderstood it. I also need to use the "prevVertex" and "nextVertex" properties to set up the ghost vertices.
But im confused. I have a simple map made up of boxes (simple square), all placed next to each other forming a closed room. Inside of it my circle i apply an impulse seeing the issue.
Now WHERE to place those ghost vertices for each square/box i placed on the view in order to solve this issue? Do i need to place ANY vertex close to the last and first vertice of chainShape or does it need to be one of the vertices of the next box to the current one? I dont understand. Box2D's manual does not explain where these ghost vertices coordinates are coming from.
Below you can see an image describing the problem.
Some code showing the physics parts for the walls and the circle:
First the wall part:
let bodyDef = b2BodyDef()
bodyDef.position = self.ptm_vec(node.position+self.offset)
let w = self.ptm(Constants.Config.wallsize)
let square = b2ChainShape()
var chains = [b2Vec2]()
chains.append(b2Vec2(-w/2,-w/2))
chains.append(b2Vec2(-w/2,w/2))
chains.append(b2Vec2(w/2,w/2))
chains.append(b2Vec2(w/2,-w/2))
square.createLoop(vertices: chains)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = square
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Wall
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Player
let wallBody = self.world.createBody(bodyDef)
wallBody.createFixture(fixtureDef)
The circle part:
let bodyDef = b2BodyDef()
bodyDef.type = b2BodyType.dynamicBody
bodyDef.position = self.ptm_vec(node.position+self.offset)
let circle = b2CircleShape()
circle.radius = self.ptm(Constants.Config.playersize)
let fixtureDef = b2FixtureDef()
fixtureDef.shape = circle
fixtureDef.density = 0.3
fixtureDef.friction = 0
fixtureDef.restitution = 1.0
fixtureDef.filter.categoryBits = Constants.Config.PhysicsCategory.Player
fixtureDef.filter.maskBits = Constants.Config.PhysicsCategory.Wall
let ballBody = self.world.createBody(bodyDef)
ballBody.linearDamping = 0
ballBody.angularDamping = 0
ballBody.createFixture(fixtureDef)
Not sure that I know of a simple solution in the case that each tile can potentially have different physics.
If your walls are all horizontal and/or vertical, you could write a class to take a row of boxes, create a single edge or rectangle body, and then on collision calculate which box (a simple a < x < b test) should interact with the colliding object, and apply the physics appropriately, manually calling the OnCollision method that you would otherwise specify as the callback for each individual box.
Alternatively, to avoid the trouble of manually testing intersection with different boxes, you could still merge all common straight edge boxes into one edge body for accurate reflections. However, you would still retain the bodies for the individual boxes. Extend the boxes so that they overlap the edge.
Now here's the trick: all box collision handlers return false, but they toggle flags on the colliding object (turning flags on OnCollision, and off OnSeparation). The OnCollision method for the edge body then processes the collision based on which flags are set.
Just make sure that the colliding body always passes through a box before it can touch an edge. That should be straightforward.

How to use ApplyForce with box2DWeb

I have a Box2DWeb sketch working ok but I am unable to figure out how to use the ApplyForce method with a body. I have attached the working codepen. On line 85, I have commented out the line that I thought would work but everything disappears when I include it.
If anyone could let me know the correct way to use it, I would be very happy. I have RTFM and seen similar posts on StackO but I still cannot work it out.
http://codepen.io/anon/pen/vOJByN?editors=101
Thanks a lot,
Steven
// single dynamic object----------------------
var fixDef2 = new b2FixtureDef;
fixDef2.density = 1.0
fixDef2.friction = 0.2;
fixDef2.restitution = 0.5;
var bodyDef2 = new b2BodyDef;
bodyDef2.type = b2Body.b2_dynamicBody;
fixDef2.shape = new b2PolygonShape;
fixDef2.shape.SetAsBox((300/SCALE)/2, (60/SCALE) / 2);
bodyDef2.position.x = canvas.width/4/SCALE;
bodyDef2.position.y = canvas.height/2/SCALE;
bodyDef2.angle = 5;
world.CreateBody(bodyDef2).CreateFixture(fixDef2);
// Apply force to object----------------------
/*bodyDef2.ApplyForce(new b2Vec2(500,50) , bodyDef2.GetWorldCenter());
*/
You should call ApplyForce method of b2Body, not of b2BodyDef. You can get b2Body object as result of world.CreateBody(bodyDef2) method.
I've changed your codepen here: http://codepen.io/anon/pen/NqZvqG
Your code:
world.CreateBody(bodyDef2).CreateFixture(fixDef2);
// Apply force to object----------------------
/*bodyDef2.ApplyForce(new b2Vec2(500,50) , bodyDef2.GetWorldCenter());
*/
My code:
var myBody = world.CreateBody(bodyDef2);
var myFixture = mybody.CreateFixture(fixDef2);
// Apply force to object
myBody.ApplyForce(new b2Vec2(500,50), myBody.GetWorldCenter());

Background infinite using corona sdk

I'm trying to scroll side a background in corona sdk (infinity background)
I used two images repeated (854x176).
I tried this function:
function mov(self, event)
if self.x < -854 then
self.x = 854
else
self.x = self.x - self.speed
end
end
it's working just fine but the problem that a small white space occurred between repetitions.
Is there a better way to do this?
One way of doing this would be to take advantage of Graphics 2.0 Engine's feature called repeating fills.
Here are the steps:
Set the default texture wrapping mode for x (you could do the same for y too):
display.setDefault("textureWrapX", "mirroredRepeat")
The modes for wrapping are:
"clampToEdge" - (default) clamped fill won't repeat
"repeat" - fill is repeated as if same tiles were placed side by side
"mirroredRepeat" - fill is repeated in a mirrored pattern, each tile being a mirror image of the one next to it
Create a rectangle the size of the background you want to have, eg. full screen
local background = display.newRect(display.contentCenterX, display.contentCenterY, 320, 480)
Fill your display object with your background image
background.fill = {type = "image", filename = "background.jpg"}
Animate it using whatever method fits your app. Below's just one way:
local function animateBackground()
transition.to(background.fill, {time=5000, x=1, delta=true, onComplete=animateBackground})
end
animateBackground()
Here you simply run transition on x property of background.fill object, delta=true indicating that we're rather using changes in x value, not final ending values (see here).
Play with the values for time, x, set delta to false, play with wrapping modes, just to see what effect it has on animation. You might even accidentally discover some cool effect which you might want to use later...
Check this excellent tutorial by Brent Sorrentino, who goes through more details on fills. Additionally, see sample code in CoronaSDK under Graphics-Premium/PatternFill.
Full code:
display.setDefault("textureWrapX", "mirroredRepeat")
local background = display.newRect(display.contentCenterX, display.contentCenterY, 320, 480)
background.fill = {type = "image", filename = "background.jpg" }
local function animateBackground()
transition.to( background.fill, { time=5000, x=1, delta=true, onComplete=animateBackground } )
end
animateBackground()

Three JS select geometry by id

Background: I'm a dev that knows JS, but is relatively new to Three JS. I've done a few small projects that involve static scenes with basic repeating animation.
I'm currently working on a modified version of Google's Globe project http://workshop.chromeexperiments.com/globe/. Looking back, I probably should have just started from scratch, but it was a good tool to see the approach their dev took. I just wish I could now update ThreeJS w/o the whole thing falling apart (too many unsupported methods and some bugs I never could fix, at least not in the hour I attempted it).
In the original, they are merging all of the geometric points into one object to speed up FPS. For my purposes, I'm updating the points on the globe using JSON, and there will never be more than 100 (probably no more than 60 actually), so they need to remain individual. I've removed the "combine" phase so I can now individually assign data to the points and then TWEEN the height change animation.
My question is, how do I manually select a single point (which is a Cube Geometry) so that I can modify the height value? I've looked through Stack Overflow and Three JS on GitHub and I'm not sure I understand the process. I'm assigning an ID to make it directly relate to the data that is being passed into it (I know WebGL adds an individual name/ID for particles, but I need something that is more directly related to what I'm doing for the sake of simplicity). That seems to work fine. But again, as a JS dev I've tried .getElementById(id) and $('#'+id) in jQuery, and neither works. I realize that Geometry objects don't behave the same way as HTML DOM objects, so I guess that's where I'm having struggles.
Code to add a point of data to the globe:
function addPoint(lat, lng, size, color, server) {
geometry = new THREE.Cube(0.75, 0.75, 1, 1, 1, 1, null, false, { px: true,
nx: true, py: true, ny: true, pz: false, nz: true});
for (var i = 0; i < geometry.vertices.length; i++) {
var vertex = geometry.vertices[i];
vertex.position.z += 0.5;
}
var point = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial ({
vertexColors: THREE.FaceColors
}));
var phi = (90 - lat) * Math.PI / 180;
var theta = (180 - lng) * Math.PI / 180;
point.position.x = 200 * Math.sin(phi) * Math.cos(theta);
point.position.y = 200 * Math.cos(phi);
point.position.z = 200 * Math.sin(phi) * Math.sin(theta);
if($('#'+server).length > 0) {
server = server+'b';
}
point.id = server;
point.lookAt(mesh.position);
point.scale.z = -size;
point.updateMatrix();
for (var i = 0; i < point.geometry.faces.length; i++) {
point.geometry.faces[i].color = color;
}
console.log(point.id);
scene.addObject(point);
}
So now to go back, I know I can't use point.id because obviously that will only reference inside the function. But I've tried 'Globe.id', 'Globe.object.id', 'object.id', and nothing seems to work. I know it is possible, I just can't seem to find a method that works.
Okay, I found a method that works for this by playing with the structure.
Essentially, the scene is labeled "globe" and all objects are its children. So treating the scene as an array, we can successfully pass an object into a var using the following structure:
Globe > Scene > Children > [Object]
Using a matching function, we loop through each item and find the desired geometric object and assign it to a temporary var for animation/adjustment:
function updatePoints(server){
var p, lineObject;
$.getJSON('/JSON/'+server+'.json', function(serverdata) {
/* script that sets p to either 0 or 1 depending on dataset */
var pointId = server+p;
//Cycle through all of the child objects and find a patch in
for(var t = 3; t < globe.scene.children.length; t++) {
if(globe.scene.children[t].name === pointId) {
//set temp var "lineObject" to the matched object
lineObject = globe.scene.children[t];
}
}
/* Manipulation based on data here, using lineObject */
});
}
I don't know if this is something that anyone else has had questions on, but I hope it helps someone else! :)
EDIT: Just realized this isn't a keyed array so I can use .length to get total # of objects

Resources