mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Merge pull request #4675 from sethalves/detect-ballistic
Detect ballistic motion + fix up simulation-owner code + fix up EntityItem constructor
This commit is contained in:
commit
0daaf20f01
9 changed files with 292 additions and 235 deletions
|
@ -39,126 +39,130 @@ hitSounds.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "Collisions-ballhitsandc
|
||||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
var screenSize = Controller.getViewportDimensions();
|
var screenSize = Controller.getViewportDimensions();
|
||||||
var reticle = Overlays.addOverlay("image", {
|
var reticle = Overlays.addOverlay("image", {
|
||||||
x: screenSize.x / 2 - 16,
|
x: screenSize.x / 2 - 16,
|
||||||
y: screenSize.y / 2 - 16,
|
y: screenSize.y / 2 - 16,
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
imageURL: HIFI_PUBLIC_BUCKET + "images/billiardsReticle.png",
|
imageURL: HIFI_PUBLIC_BUCKET + "images/billiardsReticle.png",
|
||||||
color: { red: 255, green: 255, blue: 255},
|
color: { red: 255, green: 255, blue: 255},
|
||||||
alpha: 1
|
alpha: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
function makeTable(pos) {
|
function makeTable(pos) {
|
||||||
// Top
|
// Top
|
||||||
tableParts.push(Entities.addEntity(
|
tableParts.push(Entities.addEntity(
|
||||||
{ type: "Box",
|
{ type: "Box",
|
||||||
position: pos,
|
position: pos,
|
||||||
dimensions: { x: LENGTH * SCALE, y: HEIGHT, z: WIDTH * SCALE },
|
dimensions: { x: LENGTH * SCALE, y: HEIGHT, z: WIDTH * SCALE },
|
||||||
color: { red: 0, green: 255, blue: 0 } }));
|
color: { red: 0, green: 255, blue: 0 } }));
|
||||||
// Long Bumpers
|
// Long Bumpers
|
||||||
tableParts.push(Entities.addEntity(
|
tableParts.push(Entities.addEntity(
|
||||||
{ type: "Box",
|
{ type: "Box",
|
||||||
position: { x: pos.x - LENGTH / 2.0,
|
position: { x: pos.x - LENGTH / 2.0,
|
||||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||||
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||||
color: { red: 237, green: 201, blue: 175 } }));
|
color: { red: 237, green: 201, blue: 175 } }));
|
||||||
tableParts.push(Entities.addEntity(
|
tableParts.push(Entities.addEntity(
|
||||||
{ type: "Box",
|
{ type: "Box",
|
||||||
position: { x: pos.x + LENGTH / 2.0,
|
position: { x: pos.x + LENGTH / 2.0,
|
||||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||||
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
z: pos.z - (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||||
color: { red: 237, green: 201, blue: 175 } }));
|
color: { red: 237, green: 201, blue: 175 } }));
|
||||||
|
|
||||||
tableParts.push(Entities.addEntity(
|
tableParts.push(Entities.addEntity(
|
||||||
{ type: "Box",
|
{ type: "Box",
|
||||||
position: { x: pos.x - LENGTH / 2.0,
|
position: { x: pos.x - LENGTH / 2.0,
|
||||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||||
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||||
color: { red: 237, green: 201, blue: 175 } }));
|
color: { red: 237, green: 201, blue: 175 } }));
|
||||||
tableParts.push(Entities.addEntity(
|
tableParts.push(Entities.addEntity(
|
||||||
{ type: "Box",
|
{ type: "Box",
|
||||||
position: { x: pos.x + LENGTH / 2.0,
|
position: { x: pos.x + LENGTH / 2.0,
|
||||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||||
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
z: pos.z + (WIDTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE },
|
||||||
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
dimensions: { x: (LENGTH - 3.0 * HOLE_SIZE) * SCALE / 2.0, y: BUMPER_HEIGHT, z: BUMPER_WIDTH * SCALE },
|
||||||
color: { red: 237, green: 201, blue: 175 } }));
|
color: { red: 237, green: 201, blue: 175 } }));
|
||||||
// End bumpers
|
// End bumpers
|
||||||
tableParts.push(Entities.addEntity(
|
tableParts.push(Entities.addEntity(
|
||||||
{ type: "Box",
|
{ type: "Box",
|
||||||
position: { x: pos.x + (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
|
position: { x: pos.x + (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
|
||||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||||
z: pos.z },
|
z: pos.z },
|
||||||
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
|
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
|
||||||
color: { red: 237, green: 201, blue: 175 } }));
|
color: { red: 237, green: 201, blue: 175 } }));
|
||||||
|
|
||||||
tableParts.push(Entities.addEntity(
|
tableParts.push(Entities.addEntity(
|
||||||
{ type: "Box",
|
{ type: "Box",
|
||||||
position: { x: pos.x - (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
|
position: { x: pos.x - (LENGTH / 2.0 + BUMPER_WIDTH / 2.0) * SCALE,
|
||||||
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
y: pos.y + (HEIGHT / 2.0 + BUMPER_HEIGHT / 2.0),
|
||||||
z: pos.z },
|
z: pos.z },
|
||||||
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
|
dimensions: { z: (WIDTH - 2.0 * HOLE_SIZE) * SCALE, y: BUMPER_HEIGHT, x: BUMPER_WIDTH * SCALE },
|
||||||
color: { red: 237, green: 201, blue: 175 } }));
|
color: { red: 237, green: 201, blue: 175 } }));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeBalls(pos) {
|
function makeBalls(pos) {
|
||||||
// Object balls
|
// Object balls
|
||||||
var whichBall = [ 1, 14, 15, 4, 8, 7, 12, 9, 3, 13, 10, 5, 6, 11, 2 ];
|
var whichBall = [ 1, 14, 15, 4, 8, 7, 12, 9, 3, 13, 10, 5, 6, 11, 2 ];
|
||||||
var ballNumber = 0;
|
var ballNumber = 0;
|
||||||
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
|
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
|
||||||
for (var row = 1; row <= 5; row++) {
|
for (var row = 1; row <= 5; row++) {
|
||||||
ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE);
|
ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE);
|
||||||
for (var spot = 0; spot < row; spot++) {
|
for (var spot = 0; spot < row; spot++) {
|
||||||
balls.push(Entities.addEntity(
|
balls.push(Entities.addEntity(
|
||||||
{ type: "Model",
|
{ type: "Model",
|
||||||
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/ball_" + whichBall[ballNumber].toString() + ".fbx",
|
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/ball_" +
|
||||||
position: ballPosition,
|
whichBall[ballNumber].toString() + ".fbx",
|
||||||
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
position: ballPosition,
|
||||||
rotation: Quat.fromPitchYawRollDegrees((Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20),
|
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
||||||
color: { red: 255, green: 255, blue: 255 },
|
rotation: Quat.fromPitchYawRollDegrees((Math.random() - 0.5) * 20,
|
||||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
(Math.random() - 0.5) * 20,
|
||||||
ignoreCollisions: false,
|
(Math.random() - 0.5) * 20),
|
||||||
damping: 0.50,
|
color: { red: 255, green: 255, blue: 255 },
|
||||||
shapeType: "sphere",
|
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||||
collisionsWillMove: true }));
|
velocity: {x: 0, y: -0.2, z: 0 },
|
||||||
ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE;
|
ignoreCollisions: false,
|
||||||
|
damping: 0.50,
|
||||||
|
shapeType: "sphere",
|
||||||
|
collisionsWillMove: true }));
|
||||||
|
ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE;
|
||||||
ballNumber++;
|
ballNumber++;
|
||||||
}
|
|
||||||
ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE;
|
|
||||||
}
|
}
|
||||||
|
ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
// Cue Ball
|
// Cue Ball
|
||||||
cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
|
cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
|
||||||
cueBall = Entities.addEntity(
|
cueBall = Entities.addEntity(
|
||||||
{ type: "Model",
|
{ type: "Model",
|
||||||
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/cue_ball.fbx",
|
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/cue_ball.fbx",
|
||||||
position: cuePosition,
|
position: cuePosition,
|
||||||
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
||||||
color: { red: 255, green: 255, blue: 255 },
|
color: { red: 255, green: 255, blue: 255 },
|
||||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||||
angularVelocity: { x: 0, y: 0, z: 0 },
|
angularVelocity: { x: 0, y: 0, z: 0 },
|
||||||
velocity: {x: 0, y: 0, z: 0 },
|
velocity: {x: 0, y: -0.2, z: 0 },
|
||||||
ignoreCollisions: false,
|
ignoreCollisions: false,
|
||||||
damping: 0.50,
|
damping: 0.50,
|
||||||
shapeType: "sphere",
|
shapeType: "sphere",
|
||||||
collisionsWillMove: true });
|
collisionsWillMove: true });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isObjectBall(id) {
|
function isObjectBall(id) {
|
||||||
for (var i; i < balls.length; i++) {
|
for (var i; i < balls.length; i++) {
|
||||||
if (balls[i].id == id) {
|
if (balls[i].id == id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shootCue(velocity) {
|
function shootCue(velocity) {
|
||||||
var DISTANCE_FROM_CAMERA = BALL_SIZE * 5.0 * SCALE;
|
var DISTANCE_FROM_CAMERA = BALL_SIZE * 5.0 * SCALE;
|
||||||
var camera = Camera.getPosition();
|
var camera = Camera.getPosition();
|
||||||
var forwardVector = Quat.getFront(Camera.getOrientation());
|
var forwardVector = Quat.getFront(Camera.getOrientation());
|
||||||
var cuePosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA));
|
var cuePosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA));
|
||||||
|
@ -180,14 +184,14 @@ function shootCue(velocity) {
|
||||||
density: 8000,
|
density: 8000,
|
||||||
ignoreCollisions: false,
|
ignoreCollisions: false,
|
||||||
collisionsWillMove: true
|
collisionsWillMove: true
|
||||||
});
|
});
|
||||||
print("Shot, velocity = " + velocity);
|
print("Shot, velocity = " + velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
function keyReleaseEvent(event) {
|
function keyReleaseEvent(event) {
|
||||||
if ((startStroke > 0) && event.text == "SPACE") {
|
if ((startStroke > 0) && event.text == "SPACE") {
|
||||||
var endTime = new Date().getTime();
|
var endTime = new Date().getTime();
|
||||||
var delta = endTime - startStroke;
|
var delta = endTime - startStroke;
|
||||||
shootCue(delta / 100.0);
|
shootCue(delta / 100.0);
|
||||||
startStroke = 0;
|
startStroke = 0;
|
||||||
}
|
}
|
||||||
|
@ -201,49 +205,49 @@ function keyPressEvent(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
for (var i = 0; i < tableParts.length; i++) {
|
for (var i = 0; i < tableParts.length; i++) {
|
||||||
if (!tableParts[i].isKnownID) {
|
if (!tableParts[i].isKnownID) {
|
||||||
tableParts[i] = Entities.identifyEntity(tableParts[i]);
|
tableParts[i] = Entities.identifyEntity(tableParts[i]);
|
||||||
}
|
|
||||||
Entities.deleteEntity(tableParts[i]);
|
|
||||||
}
|
}
|
||||||
for (var i = 0; i < balls.length; i++) {
|
Entities.deleteEntity(tableParts[i]);
|
||||||
if (!balls[i].isKnownID) {
|
}
|
||||||
balls[i] = Entities.identifyEntity(balls[i]);
|
for (var i = 0; i < balls.length; i++) {
|
||||||
}
|
if (!balls[i].isKnownID) {
|
||||||
Entities.deleteEntity(balls[i]);
|
balls[i] = Entities.identifyEntity(balls[i]);
|
||||||
}
|
}
|
||||||
Overlays.deleteOverlay(reticle);
|
Entities.deleteEntity(balls[i]);
|
||||||
Entities.deleteEntity(cueBall);
|
}
|
||||||
|
Overlays.deleteOverlay(reticle);
|
||||||
|
Entities.deleteEntity(cueBall);
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(deltaTime) {
|
function update(deltaTime) {
|
||||||
if (!cueBall.isKnownID) {
|
if (!cueBall.isKnownID) {
|
||||||
cueBall = Entities.identifyEntity(cueBall);
|
cueBall = Entities.identifyEntity(cueBall);
|
||||||
} else {
|
} else {
|
||||||
// Check if cue ball has fallen off table, re-drop if so
|
// Check if cue ball has fallen off table, re-drop if so
|
||||||
var cueProperties = Entities.getEntityProperties(cueBall);
|
var cueProperties = Entities.getEntityProperties(cueBall);
|
||||||
if (cueProperties.position.y < tableCenter.y) {
|
if (cueProperties.position.y < tableCenter.y) {
|
||||||
// Replace the cueball
|
// Replace the cueball
|
||||||
Entities.editEntity(cueBall, { position: cuePosition } );
|
Entities.editEntity(cueBall, { position: cuePosition } );
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function entityCollisionWithEntity(entity1, entity2, collision) {
|
function entityCollisionWithEntity(entity1, entity2, collision) {
|
||||||
/*
|
/*
|
||||||
NOT WORKING YET
|
NOT WORKING YET
|
||||||
if ((entity1.id == cueBall.id) || (entity2.id == cueBall.id)) {
|
if ((entity1.id == cueBall.id) || (entity2.id == cueBall.id)) {
|
||||||
print("Cue ball collision!");
|
print("Cue ball collision!");
|
||||||
//audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
|
//audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
|
||||||
//Audio.playSound(hitSounds[0], { position: Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())) });
|
//Audio.playSound(hitSounds[0], { position: Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())) });
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (isObjectBall(entity1.id) || isObjectBall(entity2.id)) {
|
else if (isObjectBall(entity1.id) || isObjectBall(entity2.id)) {
|
||||||
print("Object ball collision");
|
print("Object ball collision");
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
tableCenter = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
|
tableCenter = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
|
||||||
|
|
|
@ -27,75 +27,53 @@
|
||||||
|
|
||||||
bool EntityItem::_sendPhysicsUpdates = true;
|
bool EntityItem::_sendPhysicsUpdates = true;
|
||||||
|
|
||||||
void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
||||||
_id = entityItemID.id;
|
_type(EntityTypes::Unknown),
|
||||||
_creatorTokenID = entityItemID.creatorTokenID;
|
_id(entityItemID.id),
|
||||||
|
_creatorTokenID(entityItemID.creatorTokenID),
|
||||||
// init values with defaults before calling setProperties
|
_newlyCreated(false),
|
||||||
|
_lastSimulated(0),
|
||||||
|
_lastUpdated(0),
|
||||||
|
_lastEdited(0),
|
||||||
|
_lastEditedFromRemote(0),
|
||||||
|
_lastEditedFromRemoteInRemoteTime(0),
|
||||||
|
_created(UNKNOWN_CREATED_TIME),
|
||||||
|
_changedOnServer(0),
|
||||||
|
_position(ENTITY_ITEM_ZERO_VEC3),
|
||||||
|
_dimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS),
|
||||||
|
_rotation(ENTITY_ITEM_DEFAULT_ROTATION),
|
||||||
|
_glowLevel(ENTITY_ITEM_DEFAULT_GLOW_LEVEL),
|
||||||
|
_localRenderAlpha(ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA),
|
||||||
|
_density(ENTITY_ITEM_DEFAULT_DENSITY),
|
||||||
|
_volumeMultiplier(1.0f),
|
||||||
|
_velocity(ENTITY_ITEM_DEFAULT_VELOCITY),
|
||||||
|
_gravity(ENTITY_ITEM_DEFAULT_GRAVITY),
|
||||||
|
_acceleration(ENTITY_ITEM_DEFAULT_ACCELERATION),
|
||||||
|
_damping(ENTITY_ITEM_DEFAULT_DAMPING),
|
||||||
|
_lifetime(ENTITY_ITEM_DEFAULT_LIFETIME),
|
||||||
|
_script(ENTITY_ITEM_DEFAULT_SCRIPT),
|
||||||
|
_registrationPoint(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT),
|
||||||
|
_angularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY),
|
||||||
|
_angularDamping(ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING),
|
||||||
|
_visible(ENTITY_ITEM_DEFAULT_VISIBLE),
|
||||||
|
_ignoreForCollisions(ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS),
|
||||||
|
_collisionsWillMove(ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE),
|
||||||
|
_locked(ENTITY_ITEM_DEFAULT_LOCKED),
|
||||||
|
_userData(ENTITY_ITEM_DEFAULT_USER_DATA),
|
||||||
|
_simulatorID(ENTITY_ITEM_DEFAULT_SIMULATOR_ID),
|
||||||
|
_simulatorIDChangedTime(0),
|
||||||
|
_marketplaceID(ENTITY_ITEM_DEFAULT_MARKETPLACE_ID),
|
||||||
|
_physicsInfo(NULL),
|
||||||
|
_dirtyFlags(0),
|
||||||
|
_element(NULL)
|
||||||
|
{
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
_lastSimulated = now;
|
_lastSimulated = now;
|
||||||
_lastUpdated = now;
|
_lastUpdated = now;
|
||||||
_lastEdited = 0;
|
|
||||||
_lastEditedFromRemote = 0;
|
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
|
||||||
_created = UNKNOWN_CREATED_TIME;
|
|
||||||
_changedOnServer = 0;
|
|
||||||
|
|
||||||
_position = ENTITY_ITEM_ZERO_VEC3;
|
|
||||||
_dimensions = ENTITY_ITEM_DEFAULT_DIMENSIONS;
|
|
||||||
_density = ENTITY_ITEM_DEFAULT_DENSITY;
|
|
||||||
_rotation = ENTITY_ITEM_DEFAULT_ROTATION;
|
|
||||||
_glowLevel = ENTITY_ITEM_DEFAULT_GLOW_LEVEL;
|
|
||||||
_localRenderAlpha = ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA;
|
|
||||||
_velocity = ENTITY_ITEM_DEFAULT_VELOCITY;
|
|
||||||
_gravity = ENTITY_ITEM_DEFAULT_GRAVITY;
|
|
||||||
_acceleration = ENTITY_ITEM_DEFAULT_ACCELERATION;
|
|
||||||
_damping = ENTITY_ITEM_DEFAULT_DAMPING;
|
|
||||||
_lifetime = ENTITY_ITEM_DEFAULT_LIFETIME;
|
|
||||||
_script = ENTITY_ITEM_DEFAULT_SCRIPT;
|
|
||||||
_registrationPoint = ENTITY_ITEM_DEFAULT_REGISTRATION_POINT;
|
|
||||||
_angularVelocity = ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY;
|
|
||||||
_angularDamping = ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING;
|
|
||||||
_visible = ENTITY_ITEM_DEFAULT_VISIBLE;
|
|
||||||
_ignoreForCollisions = ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS;
|
|
||||||
_collisionsWillMove = ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE;
|
|
||||||
_locked = ENTITY_ITEM_DEFAULT_LOCKED;
|
|
||||||
_userData = ENTITY_ITEM_DEFAULT_USER_DATA;
|
|
||||||
_simulatorID = ENTITY_ITEM_DEFAULT_SIMULATOR_ID;
|
|
||||||
_marketplaceID = ENTITY_ITEM_DEFAULT_MARKETPLACE_ID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItem::EntityItem(const EntityItemID& entityItemID) {
|
EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : EntityItem(entityItemID)
|
||||||
_type = EntityTypes::Unknown;
|
{
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
_lastSimulated = now;
|
|
||||||
_lastUpdated = now;
|
|
||||||
_lastEdited = 0;
|
|
||||||
_lastEditedFromRemote = 0;
|
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
|
||||||
_created = UNKNOWN_CREATED_TIME;
|
|
||||||
_dirtyFlags = 0;
|
|
||||||
_changedOnServer = 0;
|
|
||||||
_element = NULL;
|
|
||||||
_simulatorIDChangedTime = 0;
|
|
||||||
_shouldClaimSimulationOwnership = false;
|
|
||||||
initFromEntityItemID(entityItemID);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) {
|
|
||||||
_type = EntityTypes::Unknown;
|
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
_lastSimulated = now;
|
|
||||||
_lastUpdated = now;
|
|
||||||
_lastEdited = 0;
|
|
||||||
_lastEditedFromRemote = 0;
|
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
|
||||||
_created = UNKNOWN_CREATED_TIME;
|
|
||||||
_dirtyFlags = 0;
|
|
||||||
_changedOnServer = 0;
|
|
||||||
_element = NULL;
|
|
||||||
_simulatorIDChangedTime = 0;
|
|
||||||
initFromEntityItemID(entityItemID);
|
|
||||||
setProperties(properties);
|
setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,8 +244,6 @@ public:
|
||||||
QUuid getSimulatorID() const { return _simulatorID; }
|
QUuid getSimulatorID() const { return _simulatorID; }
|
||||||
void setSimulatorID(const QUuid& value);
|
void setSimulatorID(const QUuid& value);
|
||||||
quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; }
|
quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; }
|
||||||
void setShouldClaimSimulationOwnership(bool value) { _shouldClaimSimulationOwnership = value; }
|
|
||||||
bool getShouldClaimSimulationOwnership() { return _shouldClaimSimulationOwnership; }
|
|
||||||
|
|
||||||
const QString& getMarketplaceID() const { return _marketplaceID; }
|
const QString& getMarketplaceID() const { return _marketplaceID; }
|
||||||
void setMarketplaceID(const QString& value) { _marketplaceID = value; }
|
void setMarketplaceID(const QString& value) { _marketplaceID = value; }
|
||||||
|
@ -305,9 +303,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
static bool _sendPhysicsUpdates;
|
static bool _sendPhysicsUpdates;
|
||||||
|
|
||||||
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
|
||||||
|
|
||||||
EntityTypes::EntityType _type;
|
EntityTypes::EntityType _type;
|
||||||
QUuid _id;
|
QUuid _id;
|
||||||
uint32_t _creatorTokenID;
|
uint32_t _creatorTokenID;
|
||||||
|
@ -347,7 +342,6 @@ protected:
|
||||||
QString _userData;
|
QString _userData;
|
||||||
QUuid _simulatorID; // id of Node which is currently responsible for simulating this Entity
|
QUuid _simulatorID; // id of Node which is currently responsible for simulating this Entity
|
||||||
quint64 _simulatorIDChangedTime; // when was _simulatorID last updated?
|
quint64 _simulatorIDChangedTime; // when was _simulatorID last updated?
|
||||||
bool _shouldClaimSimulationOwnership;
|
|
||||||
QString _marketplaceID;
|
QString _marketplaceID;
|
||||||
|
|
||||||
// NOTE: Damping is applied like this: v *= pow(1 - damping, dt)
|
// NOTE: Damping is applied like this: v *= pow(1 - damping, dt)
|
||||||
|
|
|
@ -65,17 +65,8 @@ void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) {
|
||||||
void setSimId(EntityItemProperties& propertiesWithSimID, EntityItem* entity) {
|
void setSimId(EntityItemProperties& propertiesWithSimID, EntityItem* entity) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||||
|
propertiesWithSimID.setSimulatorID(myNodeID);
|
||||||
// if this entity has non-zero physics/simulation related values, claim simulation ownership
|
entity->setSimulatorID(myNodeID);
|
||||||
if (propertiesWithSimID.velocityChanged() ||
|
|
||||||
propertiesWithSimID.rotationChanged() ||
|
|
||||||
propertiesWithSimID.containsPositionChange()) {
|
|
||||||
propertiesWithSimID.setSimulatorID(myNodeID);
|
|
||||||
entity->setSimulatorID(myNodeID);
|
|
||||||
} else if (entity->getSimulatorID() == myNodeID) {
|
|
||||||
propertiesWithSimID.setSimulatorID(QUuid()); // give up simulation ownership
|
|
||||||
entity->setSimulatorID(QUuid());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
#include "PhysicsHelpers.h"
|
#include "PhysicsHelpers.h"
|
||||||
#include "PhysicsLogging.h"
|
#include "PhysicsLogging.h"
|
||||||
|
|
||||||
static const float MEASURED_ACCELERATION_CLOSE_TO_ZERO = 0.05f;
|
static const float ACCELERATION_EQUIVALENT_EPSILON_RATIO = 0.1f;
|
||||||
|
static const quint8 STEPS_TO_DECIDE_BALLISTIC = 4;
|
||||||
|
|
||||||
QSet<EntityItem*>* _outgoingEntityList;
|
QSet<EntityItem*>* _outgoingEntityList;
|
||||||
|
|
||||||
|
@ -34,8 +35,11 @@ void EntityMotionState::enqueueOutgoingEntity(EntityItem* entity) {
|
||||||
_outgoingEntityList->insert(entity);
|
_outgoingEntityList->insert(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityMotionState::EntityMotionState(EntityItem* entity)
|
EntityMotionState::EntityMotionState(EntityItem* entity) :
|
||||||
: _entity(entity) {
|
_entity(entity),
|
||||||
|
_accelerationNearlyGravityCount(0),
|
||||||
|
_shouldClaimSimulationOwnership(false)
|
||||||
|
{
|
||||||
_type = MOTION_STATE_TYPE_ENTITY;
|
_type = MOTION_STATE_TYPE_ENTITY;
|
||||||
assert(entity != NULL);
|
assert(entity != NULL);
|
||||||
}
|
}
|
||||||
|
@ -191,7 +195,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_entity->getShouldClaimSimulationOwnership()) {
|
if (getShouldClaimSimulationOwnership()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +203,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) {
|
||||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||||
const QUuid& simulatorID = _entity->getSimulatorID();
|
const QUuid& simulatorID = _entity->getSimulatorID();
|
||||||
|
|
||||||
if (!simulatorID.isNull() && simulatorID != myNodeID) {
|
if (simulatorID != myNodeID) {
|
||||||
// some other Node owns the simulating of this, so don't broadcast the results of local simulation.
|
// some other Node owns the simulating of this, so don't broadcast the results of local simulation.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -214,10 +218,26 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
||||||
if (_outgoingPacketFlags) {
|
if (_outgoingPacketFlags) {
|
||||||
EntityItemProperties properties = _entity->getProperties();
|
EntityItemProperties properties = _entity->getProperties();
|
||||||
|
|
||||||
if (glm::length(_measuredAcceleration) < MEASURED_ACCELERATION_CLOSE_TO_ZERO) {
|
float gravityLength = glm::length(_entity->getGravity());
|
||||||
_entity->setAcceleration(glm::vec3(0.0f));
|
float accVsGravity = glm::abs(glm::length(_measuredAcceleration) - gravityLength);
|
||||||
|
if (accVsGravity < ACCELERATION_EQUIVALENT_EPSILON_RATIO * gravityLength) {
|
||||||
|
// acceleration measured during the most recent simulation step was close to gravity.
|
||||||
|
if (getAccelerationNearlyGravityCount() < STEPS_TO_DECIDE_BALLISTIC) {
|
||||||
|
// only increment this if we haven't reached the threshold yet. this is to avoid
|
||||||
|
// overflowing the counter.
|
||||||
|
incrementAccelerationNearlyGravityCount();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// acceleration wasn't similar to this entities gravity, so reset the went-ballistic counter
|
||||||
|
resetAccelerationNearlyGravityCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this entity has been accelerated at close to gravity for a certain number of simulation-steps, let
|
||||||
|
// the entity server's estimates include gravity.
|
||||||
|
if (getAccelerationNearlyGravityCount() >= STEPS_TO_DECIDE_BALLISTIC) {
|
||||||
_entity->setAcceleration(_entity->getGravity());
|
_entity->setAcceleration(_entity->getGravity());
|
||||||
|
} else {
|
||||||
|
_entity->setAcceleration(glm::vec3(0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) {
|
if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) {
|
||||||
|
@ -266,16 +286,13 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
||||||
QUuid myNodeID = nodeList->getSessionUUID();
|
QUuid myNodeID = nodeList->getSessionUUID();
|
||||||
QUuid simulatorID = _entity->getSimulatorID();
|
QUuid simulatorID = _entity->getSimulatorID();
|
||||||
|
|
||||||
if (_entity->getShouldClaimSimulationOwnership()) {
|
if (getShouldClaimSimulationOwnership()) {
|
||||||
_entity->setSimulatorID(myNodeID);
|
_entity->setSimulatorID(myNodeID);
|
||||||
properties.setSimulatorID(myNodeID);
|
properties.setSimulatorID(myNodeID);
|
||||||
_entity->setShouldClaimSimulationOwnership(false);
|
setShouldClaimSimulationOwnership(false);
|
||||||
}
|
}
|
||||||
else if (simulatorID.isNull() && !(zeroSpeed && zeroSpin)) {
|
|
||||||
// The object is moving and nobody thinks they own the motion. set this Node as the simulator
|
if (simulatorID == myNodeID && zeroSpeed && zeroSpin) {
|
||||||
_entity->setSimulatorID(myNodeID);
|
|
||||||
properties.setSimulatorID(myNodeID);
|
|
||||||
} else if (simulatorID == myNodeID && zeroSpeed && zeroSpin) {
|
|
||||||
// we are the simulator and the object has stopped. give up "simulator" status
|
// we are the simulator and the object has stopped. give up "simulator" status
|
||||||
_entity->setSimulatorID(QUuid());
|
_entity->setSimulatorID(QUuid());
|
||||||
properties.setSimulatorID(QUuid());
|
properties.setSimulatorID(QUuid());
|
||||||
|
|
|
@ -62,10 +62,18 @@ public:
|
||||||
virtual uint32_t getIncomingDirtyFlags() const;
|
virtual uint32_t getIncomingDirtyFlags() const;
|
||||||
virtual void clearIncomingDirtyFlags(uint32_t flags) { _entity->clearDirtyFlags(flags); }
|
virtual void clearIncomingDirtyFlags(uint32_t flags) { _entity->clearDirtyFlags(flags); }
|
||||||
|
|
||||||
EntityItem* getEntity() const { return _entity; }
|
void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; }
|
||||||
|
void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; }
|
||||||
|
quint8 getAccelerationNearlyGravityCount() { return _accelerationNearlyGravityCount; }
|
||||||
|
|
||||||
|
virtual EntityItem* getEntity() const { return _entity; }
|
||||||
|
virtual void setShouldClaimSimulationOwnership(bool value) { _shouldClaimSimulationOwnership = value; }
|
||||||
|
virtual bool getShouldClaimSimulationOwnership() { return _shouldClaimSimulationOwnership; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EntityItem* _entity;
|
EntityItem* _entity;
|
||||||
|
quint8 _accelerationNearlyGravityCount;
|
||||||
|
bool _shouldClaimSimulationOwnership;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityMotionState_h
|
#endif // hifi_EntityMotionState_h
|
||||||
|
|
|
@ -111,6 +111,12 @@ public:
|
||||||
virtual bool isMoving() const = 0;
|
virtual bool isMoving() const = 0;
|
||||||
|
|
||||||
friend class PhysicsEngine;
|
friend class PhysicsEngine;
|
||||||
|
|
||||||
|
// these are here so we can call into EntityMotionObject with a base-class pointer
|
||||||
|
virtual EntityItem* getEntity() const { return NULL; }
|
||||||
|
virtual void setShouldClaimSimulationOwnership(bool value) { }
|
||||||
|
virtual bool getShouldClaimSimulationOwnership() { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setRigidBody(btRigidBody* body);
|
void setRigidBody(btRigidBody* body);
|
||||||
|
|
||||||
|
|
|
@ -348,10 +348,10 @@ void PhysicsEngine::stepSimulation() {
|
||||||
_characterController->postSimulation();
|
_characterController->postSimulation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
computeCollisionEvents();
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
_entityTree->unlock();
|
_entityTree->unlock();
|
||||||
|
|
||||||
computeCollisionEvents();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,6 +369,9 @@ void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) {
|
||||||
void PhysicsEngine::computeCollisionEvents() {
|
void PhysicsEngine::computeCollisionEvents() {
|
||||||
BT_PROFILE("computeCollisionEvents");
|
BT_PROFILE("computeCollisionEvents");
|
||||||
|
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
QUuid myNodeID = nodeList->getSessionUUID();
|
||||||
|
|
||||||
const btCollisionObject* characterCollisionObject =
|
const btCollisionObject* characterCollisionObject =
|
||||||
_characterController ? _characterController->getCollisionObject() : NULL;
|
_characterController ? _characterController->getCollisionObject() : NULL;
|
||||||
|
|
||||||
|
@ -388,21 +391,31 @@ void PhysicsEngine::computeCollisionEvents() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* a = objectA->getUserPointer();
|
ObjectMotionState* a = static_cast<ObjectMotionState*>(objectA->getUserPointer());
|
||||||
void* b = objectB->getUserPointer();
|
ObjectMotionState* b = static_cast<ObjectMotionState*>(objectB->getUserPointer());
|
||||||
|
EntityItem* entityA = a ? a->getEntity() : NULL;
|
||||||
|
EntityItem* entityB = b ? b->getEntity() : NULL;
|
||||||
|
bool aIsDynamic = entityA && !objectA->isStaticOrKinematicObject();
|
||||||
|
bool bIsDynamic = entityB && !objectB->isStaticOrKinematicObject();
|
||||||
|
|
||||||
if (a || b) {
|
if (a || b) {
|
||||||
// the manifold has up to 4 distinct points, but only extract info from the first
|
// the manifold has up to 4 distinct points, but only extract info from the first
|
||||||
_contactMap[ContactKey(a, b)].update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset);
|
_contactMap[ContactKey(a, b)].update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset);
|
||||||
|
}
|
||||||
// if our character capsule is colliding with something dynamic, claim simulation ownership.
|
// collisions cause infectious spread of simulation-ownership. we also attempt to take
|
||||||
// see EntityMotionState::sendUpdate
|
// ownership of anything that collides with our avatar.
|
||||||
if (objectA == characterCollisionObject && !objectB->isStaticOrKinematicObject() && b) {
|
if ((aIsDynamic && entityA->getSimulatorID() == myNodeID) ||
|
||||||
EntityItem* entityB = static_cast<EntityMotionState*>(b)->getEntity();
|
(a && a->getShouldClaimSimulationOwnership()) ||
|
||||||
entityB->setShouldClaimSimulationOwnership(true);
|
(objectA == characterCollisionObject)) {
|
||||||
|
if (bIsDynamic) {
|
||||||
|
b->setShouldClaimSimulationOwnership(true);
|
||||||
}
|
}
|
||||||
if (objectB == characterCollisionObject && !objectA->isStaticOrKinematicObject() && a) {
|
}
|
||||||
EntityItem* entityA = static_cast<EntityMotionState*>(a)->getEntity();
|
if ((bIsDynamic && entityB->getSimulatorID() == myNodeID) ||
|
||||||
entityA->setShouldClaimSimulationOwnership(true);
|
(b && b->getShouldClaimSimulationOwnership()) ||
|
||||||
|
(objectB == characterCollisionObject)) {
|
||||||
|
if (aIsDynamic) {
|
||||||
|
a->setShouldClaimSimulationOwnership(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +426,6 @@ void PhysicsEngine::computeCollisionEvents() {
|
||||||
// scan known contacts and trigger events
|
// scan known contacts and trigger events
|
||||||
ContactMap::iterator contactItr = _contactMap.begin();
|
ContactMap::iterator contactItr = _contactMap.begin();
|
||||||
|
|
||||||
|
|
||||||
while (contactItr != _contactMap.end()) {
|
while (contactItr != _contactMap.end()) {
|
||||||
ObjectMotionState* A = static_cast<ObjectMotionState*>(contactItr->first._a);
|
ObjectMotionState* A = static_cast<ObjectMotionState*>(contactItr->first._a);
|
||||||
ObjectMotionState* B = static_cast<ObjectMotionState*>(contactItr->first._b);
|
ObjectMotionState* B = static_cast<ObjectMotionState*>(contactItr->first._b);
|
||||||
|
@ -521,9 +533,55 @@ void PhysicsEngine::addObject(const ShapeInfo& shapeInfo, btCollisionShape* shap
|
||||||
motionState->resetMeasuredAcceleration();
|
motionState->resetMeasuredAcceleration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsEngine::bump(EntityItem* bumpEntity) {
|
||||||
|
// If this node is doing something like deleting an entity, scan for contacts involving the
|
||||||
|
// entity. For each found, flag the other entity involved as being simulated by this node.
|
||||||
|
lock();
|
||||||
|
int numManifolds = _collisionDispatcher->getNumManifolds();
|
||||||
|
for (int i = 0; i < numManifolds; ++i) {
|
||||||
|
btPersistentManifold* contactManifold = _collisionDispatcher->getManifoldByIndexInternal(i);
|
||||||
|
if (contactManifold->getNumContacts() > 0) {
|
||||||
|
const btCollisionObject* objectA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
|
||||||
|
const btCollisionObject* objectB = static_cast<const btCollisionObject*>(contactManifold->getBody1());
|
||||||
|
if (objectA && objectB) {
|
||||||
|
void* a = objectA->getUserPointer();
|
||||||
|
void* b = objectB->getUserPointer();
|
||||||
|
if (a && b) {
|
||||||
|
EntityMotionState* entityMotionStateA = static_cast<EntityMotionState*>(a);
|
||||||
|
EntityMotionState* entityMotionStateB = static_cast<EntityMotionState*>(b);
|
||||||
|
EntityItem* entityA = entityMotionStateA ? entityMotionStateA->getEntity() : NULL;
|
||||||
|
EntityItem* entityB = entityMotionStateB ? entityMotionStateB->getEntity() : NULL;
|
||||||
|
if (entityA && entityB) {
|
||||||
|
if (entityA == bumpEntity) {
|
||||||
|
entityMotionStateB->setShouldClaimSimulationOwnership(true);
|
||||||
|
if (!objectB->isActive()) {
|
||||||
|
objectB->setActivationState(ACTIVE_TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entityB == bumpEntity) {
|
||||||
|
entityMotionStateA->setShouldClaimSimulationOwnership(true);
|
||||||
|
if (!objectA->isActive()) {
|
||||||
|
objectA->setActivationState(ACTIVE_TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) {
|
void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) {
|
||||||
assert(motionState);
|
assert(motionState);
|
||||||
btRigidBody* body = motionState->getRigidBody();
|
btRigidBody* body = motionState->getRigidBody();
|
||||||
|
|
||||||
|
// set the about-to-be-deleted entity active in order to wake up the island it's part of. this is done
|
||||||
|
// so that anything resting on top of it will fall.
|
||||||
|
// body->setActivationState(ACTIVE_TAG);
|
||||||
|
EntityItem* entity = static_cast<EntityMotionState*>(motionState)->getEntity();
|
||||||
|
bump(entity);
|
||||||
|
|
||||||
if (body) {
|
if (body) {
|
||||||
const btCollisionShape* shape = body->getCollisionShape();
|
const btCollisionShape* shape = body->getCollisionShape();
|
||||||
_dynamicsWorld->removeRigidBody(body);
|
_dynamicsWorld->removeRigidBody(body);
|
||||||
|
|
|
@ -98,6 +98,7 @@ private:
|
||||||
// return 'true' of update was successful
|
// return 'true' of update was successful
|
||||||
bool updateObjectHard(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags);
|
bool updateObjectHard(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags);
|
||||||
void updateObjectEasy(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags);
|
void updateObjectEasy(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags);
|
||||||
|
void bump(EntityItem* bumpEntity);
|
||||||
|
|
||||||
btClock _clock;
|
btClock _clock;
|
||||||
btDefaultCollisionConfiguration* _collisionConfig = NULL;
|
btDefaultCollisionConfiguration* _collisionConfig = NULL;
|
||||||
|
|
Loading…
Reference in a new issue