How to implement Mororised grabber approach on doors?
How to implement Mororised grabber approach on doors?
Hi again Norbo
So far, I have only seen grabber shift it's corresponding entity towards the goal position, but how about rotating? The door needs to be rotated, right?
Also, to avoid the crusher-of-everything-in-the-way door, I should give it some mass, but then it would be vulnerable if another object hit it, and could literally move out of the door frame (very undesirable).
Could you give me a hint on what the correct approach should be?
Thank you
So far, I have only seen grabber shift it's corresponding entity towards the goal position, but how about rotating? The door needs to be rotated, right?
Also, to avoid the crusher-of-everything-in-the-way door, I should give it some mass, but then it would be vulnerable if another object hit it, and could literally move out of the door frame (very undesirable).
Could you give me a hint on what the correct approach should be?
Thank you
Re: How to implement Mororised grabber approach on doors?
The door could be held in place with a RevoluteJoint. If you don't want the door opening backward, activate the RevoluteJoint.Limit and configure it so that it can only open one way. With a sufficiently hard limit, the door won't be able to budge beyond the defined values.
If the user grabs the constrained door, the door will rotate in response since that's all it can do. Try grabbing the robot arm in the RobotArmDemo to see how it responds.
If the user grabs the constrained door, the door will rotate in response since that's all it can do. Try grabbing the robot arm in the RobotArmDemo to see how it responds.
Re: How to implement Mororised grabber approach on doors?
So how do I actually set it up?
I've tried a few different approaches like
but it freezes my character's moving controls.
What should I constrain it to? The room?
I've tried a few different approaches like
Code: Select all
doorJoint = new RevoluteJoint(door, room, door.Position, Vector3.Right);
doorJoint.IsActive = true;
doorJoint.Motor.IsActive = true;
space.Add(doorJoint);
What should I constrain it to? The room?
Re: How to implement Mororised grabber approach on doors?
Oops, I still have the door as a kinematic entity, I should change that first.
Re: How to implement Mororised grabber approach on doors?
Here's one possible example implementation:
There's more examples of configuring constraints in the demos, too.
Code: Select all
var door = new Box(new Vector3(0, 1.55f, 5), 2, 3, .5f, 10);
RevoluteJoint revoluteJoint = new RevoluteJoint(null, door, door.Position + new Vector3(-1, 0, 0), Vector3.Up);
//The revolute joint's BallSocketJoint and RevoluteAngularJoint are active by default. Its RevoluteLimit, however, is not.
revoluteJoint.Limit.IsActive = true;
//The RevoluteJoint constructor configures itself on a guess. Since we're connecting to null, this guess isn't so great.
//Configure the bases of the joints to match our expectations.
//The first parameter in the basis corresponds to the axis of rotation.
//The second parameter defines the angle which we pick to represent 0.
//The basis is attached to entity A, or in this case, null (the world).
revoluteJoint.Limit.Basis.SetWorldAxes(Vector3.Up, Vector3.Right);
//The test axis is attached to the second entity. This is used to measure the current angle to determine if the limit has been violated.
//We'll align it with the 0 angle direction we picked before.
revoluteJoint.Limit.TestAxis = Vector3.Right;
//Set up the minimum and maximum angles.
revoluteJoint.Limit.MinimumAngle = -MathHelper.Pi;
revoluteJoint.Limit.MaximumAngle = 0;
Space.Add(door);
Space.Add(revoluteJoint);
Re: How to implement Mororised grabber approach on doors?
That's almost perfect now, the only thing that is wrong, is that the door can now also twist a little bit around forward axis.
And when I let it go, it returns back to the normal position, I don't know why.
Does it have something to do with my other code?
And when I let it go, it returns back to the normal position, I don't know why.
Does it have something to do with my other code?
Code: Select all
public Door(Space s, string modelName, int mass, Vector3 pos, int specialDoor, int modelsIndex, Game game) {
Game = game;
space = s;
position = pos;
special = specialDoor;
speed = 1;
doorstate = DoorState.shut;
moveState = MoveState.still;
Model temp = ((Game1)Game).Content.Load<Model>("Models/" + modelName);
Vector3[] vertices;
int[] indices;
TriangleMesh.GetVerticesAndIndicesFromModel(temp, out vertices, out indices);
ConvexHull ch = new ConvexHull(vertices);
ch.Tag = "door";
ch.IsAffectedByGravity = false;
float offset = 17;
ch.CollisionInformation.LocalPosition = new Vector3(offset, 0, 0);
ch.Tag = "door";
ch.CollisionInformation.Tag = "" + modelsIndex;
ch.Mass = 100;
cModel = new CModel(temp, Matrix.CreateTranslation(-ch.Position + ch.CollisionInformation.LocalPosition), ((Game1)Game), ch);
ch.Position += position;
space.Add(ch);
RevoluteJoint revoluteJoint = new RevoluteJoint(null, space.Entities[space.Entities.Count - 1], space.Entities[space.Entities.Count - 1].Position + new Vector3(-1, 0, 0), Vector3.Up);
//The revolute joint's BallSocketJoint and RevoluteAngularJoint are active by default. Its RevoluteLimit, however, is not.
revoluteJoint.Limit.IsActive = true;
//The RevoluteJoint constructor configures itself on a guess. Since we're connecting to null, this guess isn't so great.
//Configure the bases of the joints to match our expectations.
//The first parameter in the basis corresponds to the axis of rotation.
//The second parameter defines the angle which we pick to represent 0.
//The basis is attached to entity A, or in this case, null (the world).
revoluteJoint.Limit.Basis.SetWorldAxes(Vector3.Up, Vector3.Right);
//The test axis is attached to the second entity. This is used to measure the current angle to determine if the limit has been violated.
//We'll align it with the 0 angle direction we picked before.
revoluteJoint.Limit.TestAxis = Vector3.Right;
//Set up the minimum and maximum angles.
revoluteJoint.Limit.MinimumAngle = -MathHelper.Pi;
revoluteJoint.Limit.MaximumAngle = 0;
space.Add(revoluteJoint);
}
Re: How to implement Mororised grabber approach on doors?
The door's mass is 100 in your example, and 10 in mine. If your grabber scales its strength based upon the mass of the object like the BEPUphysicsDemos one does, then it's applying 10x more force to the door. The hinge holding the door is springlike- applying 10x more force will shove it out of place more easily since the spring isn't any stronger.
So, do at least one of the following:
1) Strengthen the door constraints. Here's an example of how to strengthen the hinge itself:
2) Lower the door mass.
3) Don't scale the grabber strength by the picked object's mass.
So, do at least one of the following:
1) Strengthen the door constraints. Here's an example of how to strengthen the hinge itself:
Code: Select all
revoluteJoint.AngularJoint.SpringSettings.DampingConstant *= 10;
revoluteJoint.AngularJoint.SpringSettings.StiffnessConstant *= 10;
3) Don't scale the grabber strength by the picked object's mass.
Re: How to implement Mororised grabber approach on doors?
Ah, that's what it was! Ok, now it's acting a little weird, because it collides with the house (I think)
Is it possible to remove collision detection between a door and a house?
I was going to use
but then I realized the static geometry isn't in .Entities list.
Is it possible to remove collision detection between a door and a house?
I was going to use
Code: Select all
CollisionRules.AddRule(ch, space.Entities[roomIndex], CollisionRule.NoBroadPhase);
Re: How to implement Mororised grabber approach on doors?
That method is indeed what you'd want to use. A StaticMesh can be passed as a parameter- it takes any object which owns a CollisionRules instance, directly or indirectly.