mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 01:48:59 +02:00
Merge pull request #4177 from ZappoMan/fixGlitches
Some physics improvements
This commit is contained in:
commit
6b6e846378
13 changed files with 213 additions and 101 deletions
|
@ -486,7 +486,8 @@ function mousePressEvent(event) {
|
|||
if (clickedOverlay == offButton) {
|
||||
Script.stop();
|
||||
} else if (clickedOverlay == platformButton) {
|
||||
makePlatform(-9.8, 1.0, 5);
|
||||
var platformSize = 3;
|
||||
makePlatform(-9.8, 1.0, platformSize);
|
||||
} else if (clickedOverlay == gridButton) {
|
||||
makeGrid("Box", 1.0, 3);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ function setupMenus() {
|
|||
}
|
||||
if (!Menu.menuExists("Developer > Entities")) {
|
||||
Menu.addMenu("Developer > Entities");
|
||||
|
||||
// NOTE: these menu items aren't currently working. I've temporarily removed them. Will add them back once we
|
||||
// rewire these to work
|
||||
/*
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Bounds", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Triangles", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false });
|
||||
|
@ -26,9 +30,26 @@ function setupMenus() {
|
|||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false });
|
||||
*/
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't send collision updates to server", isCheckable: true, isChecked: false });
|
||||
}
|
||||
}
|
||||
|
||||
Menu.menuItemEvent.connect(function (menuItem) {
|
||||
print("menuItemEvent() in JS... menuItem=" + menuItem);
|
||||
|
||||
if (menuItem == "Don't send collision updates to server") {
|
||||
var dontSendUpdates = Menu.isOptionChecked("Don't send collision updates to server");
|
||||
print(" dontSendUpdates... checked=" + dontSendUpdates);
|
||||
Entities.setSendPhysicsUpdates(!dontSendUpdates);
|
||||
}
|
||||
});
|
||||
|
||||
setupMenus();
|
||||
|
||||
// register our scriptEnding callback
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
function scriptEnding() {
|
||||
Menu.removeMenu("Developer > Entities");
|
||||
}
|
||||
|
|
|
@ -101,3 +101,12 @@ void BoxEntityItem::computeShapeInfo(ShapeInfo& info) const {
|
|||
info.setBox(halfExtents);
|
||||
}
|
||||
|
||||
void BoxEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qDebug() << " BOX EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qDebug() << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
|
||||
qDebug() << " position:" << debugTreeVector(_position);
|
||||
qDebug() << " dimensions:" << debugTreeVector(_dimensions);
|
||||
qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ public:
|
|||
|
||||
void computeShapeInfo(ShapeInfo& info) const;
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
protected:
|
||||
rgbColor _color;
|
||||
};
|
||||
|
|
|
@ -36,6 +36,11 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemI
|
|||
int sizeOut = 0;
|
||||
|
||||
if (EntityItemProperties::encodeEntityEditPacket(type, modelID, properties, &bufferOut[0], _maxPacketSize, sizeOut)) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "calling queueOctreeEditMessage()...";
|
||||
qDebug() << " id:" << modelID;
|
||||
qDebug() << " properties:" << properties;
|
||||
#endif
|
||||
queueOctreeEditMessage(type, bufferOut, sizeOut);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "EntityItem.h"
|
||||
#include "EntityTree.h"
|
||||
|
||||
bool EntityItem::_sendPhysicsUpdates = true;
|
||||
|
||||
void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
||||
_id = entityItemID.id;
|
||||
_creatorTokenID = entityItemID.creatorTokenID;
|
||||
|
@ -165,13 +167,12 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
|
||||
quint64 lastEdited = getLastEdited();
|
||||
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
float editedAgo = getEditedAgo();
|
||||
QString agoAsString = formatSecondsElapsed(editedAgo);
|
||||
qDebug() << "Writing entity " << getEntityItemID() << " to buffer, lastEdited =" << lastEdited
|
||||
<< " ago=" << editedAgo << "seconds - " << agoAsString;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool successIDFits = false;
|
||||
bool successTypeFits = false;
|
||||
|
@ -225,11 +226,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " APPEND_ENTITY_PROPERTY() PROP_DIMENSIONS:" << getDimensions();
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, appendValue, getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity());
|
||||
|
@ -308,7 +304,6 @@ int EntityItem::expectedBytes() {
|
|||
|
||||
|
||||
int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) {
|
||||
|
||||
|
@ -373,17 +368,21 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
_created = createdFromBuffer;
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
quint64 lastEdited = getLastEdited();
|
||||
float editedAgo = getEditedAgo();
|
||||
QString agoAsString = formatSecondsElapsed(editedAgo);
|
||||
QString ageAsString = formatSecondsElapsed(getAge());
|
||||
qDebug() << "------------------------------------------";
|
||||
qDebug() << "Loading entity " << getEntityItemID() << " from buffer...";
|
||||
qDebug() << "------------------------------------------";
|
||||
debugDump();
|
||||
qDebug() << "------------------------------------------";
|
||||
qDebug() << " _created =" << _created;
|
||||
qDebug() << " age=" << getAge() << "seconds - " << ageAsString;
|
||||
qDebug() << " lastEdited =" << lastEdited;
|
||||
qDebug() << " ago=" << editedAgo << "seconds - " << agoAsString;
|
||||
}
|
||||
#endif
|
||||
|
||||
quint64 lastEditedFromBuffer = 0;
|
||||
quint64 lastEditedFromBufferAdjusted = 0;
|
||||
|
@ -400,20 +399,18 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
bool fromSameServerEdit = (lastEditedFromBuffer == _lastEditedFromRemoteInRemoteTime);
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "data from server **************** ";
|
||||
qDebug() << " entityItemID=" << getEntityItemID();
|
||||
qDebug() << " now=" << now;
|
||||
qDebug() << " getLastEdited()=" << getLastEdited();
|
||||
qDebug() << " lastEditedFromBuffer=" << lastEditedFromBuffer << " (BEFORE clockskew adjust)";
|
||||
qDebug() << " clockSkew=" << clockSkew;
|
||||
qDebug() << " lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted << " (AFTER clockskew adjust)";
|
||||
qDebug() << " _lastEditedFromRemote=" << _lastEditedFromRemote
|
||||
<< " (our local time the last server edit we accepted)";
|
||||
qDebug() << " _lastEditedFromRemoteInRemoteTime=" << _lastEditedFromRemoteInRemoteTime
|
||||
<< " (remote time the last server edit we accepted)";
|
||||
qDebug() << " fromSameServerEdit=" << fromSameServerEdit;
|
||||
}
|
||||
qDebug() << " entityItemID:" << getEntityItemID();
|
||||
qDebug() << " now:" << now;
|
||||
qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
qDebug() << " lastEditedFromBuffer:" << debugTime(lastEditedFromBuffer, now);
|
||||
qDebug() << " clockSkew:" << debugTimeOnly(clockSkew);
|
||||
qDebug() << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
qDebug() << " _lastEditedFromRemote:" << debugTime(_lastEditedFromRemote, now);
|
||||
qDebug() << " _lastEditedFromRemoteInRemoteTime:" << debugTime(_lastEditedFromRemoteInRemoteTime, now);
|
||||
qDebug() << " fromSameServerEdit:" << fromSameServerEdit;
|
||||
#endif
|
||||
|
||||
bool ignoreServerPacket = false; // assume we'll use this server packet
|
||||
|
||||
|
@ -436,14 +433,16 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
if (ignoreServerPacket) {
|
||||
overwriteLocalData = false;
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "IGNORING old data from server!!! ****************";
|
||||
}
|
||||
debugDump();
|
||||
#endif
|
||||
} else {
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "USING NEW data from server!!! ****************";
|
||||
}
|
||||
debugDump();
|
||||
#endif
|
||||
|
||||
// don't allow _lastEdited to be in the future
|
||||
_lastEdited = lastEditedFromBufferAdjusted;
|
||||
|
@ -461,11 +460,11 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
quint64 updateDelta = updateDeltaCoder;
|
||||
if (overwriteLocalData) {
|
||||
_lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that
|
||||
if (wantDebug) {
|
||||
qDebug() << "_lastUpdated =" << _lastUpdated;
|
||||
qDebug() << "_lastEdited=" << _lastEdited;
|
||||
qDebug() << "lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted;
|
||||
}
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " _lastUpdated:" << debugTime(_lastUpdated, now);
|
||||
qDebug() << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||
qDebug() << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
#endif
|
||||
}
|
||||
encodedUpdateDelta = updateDeltaCoder; // determine true length
|
||||
dataAt += encodedUpdateDelta.size();
|
||||
|
@ -479,16 +478,26 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
quint64 simulatedDelta = simulatedDeltaCoder;
|
||||
if (overwriteLocalData) {
|
||||
_lastSimulated = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
||||
if (wantDebug) {
|
||||
qDebug() << "_lastSimulated =" << _lastSimulated;
|
||||
qDebug() << "_lastEdited=" << _lastEdited;
|
||||
qDebug() << "lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted;
|
||||
}
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " _lastSimulated:" << debugTime(_lastSimulated, now);
|
||||
qDebug() << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||
qDebug() << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
#endif
|
||||
}
|
||||
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
||||
dataAt += encodedSimulatedDelta.size();
|
||||
bytesRead += encodedSimulatedDelta.size();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
if (overwriteLocalData) {
|
||||
qDebug() << "EntityItem::readEntityDataFromBuffer()... changed entity:" << getEntityItemID();
|
||||
qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
qDebug() << " getLastSimulated:" << debugTime(getLastSimulated(), now);
|
||||
qDebug() << " getLastUpdated:" << debugTime(getLastUpdated(), now);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Property Flags
|
||||
QByteArray encodedPropertyFlags = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||
|
@ -508,23 +517,11 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
if (overwriteLocalData) {
|
||||
setRadius(fromBuffer);
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() OLD FORMAT... found PROP_RADIUS";
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensions);
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() NEW FORMAT... look for PROP_DIMENSIONS";
|
||||
}
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() _dimensions:" << getDimensionsInMeters() << " in meters";
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DENSITY, float, updateDensity);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocity);
|
||||
|
@ -541,23 +538,22 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA,setUserData);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() _registrationPoint:" << _registrationPoint;
|
||||
qDebug() << " readEntityDataFromBuffer() _visible:" << _visible;
|
||||
qDebug() << " readEntityDataFromBuffer() _ignoreForCollisions:" << _ignoreForCollisions;
|
||||
qDebug() << " readEntityDataFromBuffer() _collisionsWillMove:" << _collisionsWillMove;
|
||||
}
|
||||
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData);
|
||||
|
||||
recalculateCollisionShape();
|
||||
if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY))) {
|
||||
// TODO: Andrew & Brad to discuss -- this probably should not be "now" but instead should be the last
|
||||
// simulated time from server. The logic should maybe be: the position changed from the server, so the
|
||||
// position we just set can be thought of as the position at the time it was last simulated by the
|
||||
// server (clock skew adjusted). By setting it to "now" we are saying that the last position is to be
|
||||
// considered to be the correct position for "now" which is likely in the future from when it actually
|
||||
// was at that last known positition.
|
||||
// NOTE: This code is attempting to "repair" the old data we just got from the server to make it more
|
||||
// closely match where the entities should be if they'd stepped forward in time to "now". The server
|
||||
// is sending us data with a known "last simulated" time. That time is likely in the past, and therefore
|
||||
// this "new" data is actually slightly out of date. We calculate the time we need to skip forward and
|
||||
// use our simulation helper routine to get a best estimate of where the entity should be.
|
||||
float skipTimeForward = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
|
||||
if (skipTimeForward > 0.0f) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "skipTimeForward:" << skipTimeForward;
|
||||
#endif
|
||||
simulateKinematicMotion(skipTimeForward);
|
||||
}
|
||||
_lastSimulated = now;
|
||||
}
|
||||
}
|
||||
|
@ -583,13 +579,12 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s
|
|||
memcpy(&lastEditedInLocalTime, dataAt, sizeof(lastEditedInLocalTime));
|
||||
quint64 lastEditedInServerTime = lastEditedInLocalTime + clockSkew;
|
||||
memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime));
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug("EntityItem::adjustEditPacketForClockSkew()...");
|
||||
qDebug() << " lastEditedInLocalTime: " << lastEditedInLocalTime;
|
||||
qDebug() << " clockSkew: " << clockSkew;
|
||||
qDebug() << " lastEditedInServerTime: " << lastEditedInServerTime;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float EntityItem::computeMass() const {
|
||||
|
@ -644,15 +639,13 @@ bool EntityItem::isRestingOnSurface() const {
|
|||
}
|
||||
|
||||
void EntityItem::simulate(const quint64& now) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (_lastSimulated == 0) {
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "********** EntityItem::simulate()";
|
||||
qDebug() << " entity ID=" << getEntityItemID();
|
||||
qDebug() << " now=" << now;
|
||||
|
@ -687,27 +680,23 @@ void EntityItem::simulate(const quint64& now) {
|
|||
qDebug() << " getAge()=" << getAge();
|
||||
qDebug() << " getLifetime()=" << getLifetime();
|
||||
}
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " ********** EntityItem::simulate() .... SETTING _lastSimulated=" << _lastSimulated;
|
||||
}
|
||||
#endif
|
||||
|
||||
simulateKinematicMotion(timeElapsed);
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
||||
bool wantDebug = false;
|
||||
if (hasAngularVelocity()) {
|
||||
// angular damping
|
||||
glm::vec3 angularVelocity = getAngularVelocity();
|
||||
if (_angularDamping > 0.0f) {
|
||||
angularVelocity *= powf(1.0f - _angularDamping, timeElapsed);
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " angularDamping :" << _angularDamping;
|
||||
qDebug() << " newAngularVelocity:" << angularVelocity;
|
||||
}
|
||||
#endif
|
||||
setAngularVelocity(angularVelocity);
|
||||
}
|
||||
|
||||
|
@ -735,19 +724,19 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
|||
glm::vec3 velocity = getVelocity();
|
||||
if (_damping > 0.0f) {
|
||||
velocity *= powf(1.0f - _damping, timeElapsed);
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " damping:" << _damping;
|
||||
qDebug() << " velocity AFTER dampingResistance:" << velocity;
|
||||
qDebug() << " glm::length(velocity):" << glm::length(velocity);
|
||||
qDebug() << " velocityEspilon :" << ENTITY_ITEM_EPSILON_VELOCITY_LENGTH;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// integrate position forward
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 newPosition = position + (velocity * timeElapsed);
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " EntityItem::simulate()....";
|
||||
qDebug() << " timeElapsed:" << timeElapsed;
|
||||
qDebug() << " old AACube:" << getMaximumAACube();
|
||||
|
@ -757,7 +746,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
|||
qDebug() << " getDistanceToBottomOfEntity():" << getDistanceToBottomOfEntity() * (float)TREE_SCALE << " in meters";
|
||||
qDebug() << " newPosition:" << newPosition;
|
||||
qDebug() << " glm::distance(newPosition, position):" << glm::distance(newPosition, position);
|
||||
}
|
||||
#endif
|
||||
|
||||
position = newPosition;
|
||||
|
||||
|
@ -780,12 +769,12 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
|||
setVelocity(velocity);
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " new position:" << position;
|
||||
qDebug() << " new velocity:" << velocity;
|
||||
qDebug() << " new AACube:" << getMaximumAACube();
|
||||
qDebug() << " old getAABox:" << getAABox();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -859,13 +848,12 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
if (somethingChanged) {
|
||||
somethingChangedNotification(); // notify derived classes that something has changed
|
||||
bool wantDebug = false;
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
int elapsed = now - getLastEdited();
|
||||
qDebug() << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
#endif
|
||||
if (_created != UNKNOWN_CREATED_TIME) {
|
||||
setLastEdited(now);
|
||||
}
|
||||
|
@ -1007,15 +995,6 @@ void EntityItem::setRadius(float value) {
|
|||
float diameter = value * 2.0f;
|
||||
float maxDimension = sqrt((diameter * diameter) / 3.0f);
|
||||
_dimensions = glm::vec3(maxDimension, maxDimension, maxDimension);
|
||||
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityItem::setRadius()...";
|
||||
qDebug() << " radius:" << value;
|
||||
qDebug() << " diameter:" << diameter;
|
||||
qDebug() << " maxDimension:" << maxDimension;
|
||||
qDebug() << " _dimensions:" << _dimensions;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: get rid of all users of this function...
|
||||
|
|
|
@ -36,13 +36,16 @@ class EntityTreeElementExtraEncodeData;
|
|||
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
|
||||
#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { };
|
||||
|
||||
#define debugTime(T, N) qPrintable(QString("%1 [ %2 ago]").arg(T, 16, 10).arg(formatUsecTime(N - T), 15))
|
||||
#define debugTimeOnly(T) qPrintable(QString("%1").arg(T, 16, 10))
|
||||
#define debugTreeVector(V) V << "[" << (V * (float)TREE_SCALE) << " in meters ]"
|
||||
|
||||
|
||||
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
|
||||
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
|
||||
/// one directly, instead you must only construct one of it's derived classes with additional features.
|
||||
class EntityItem {
|
||||
friend class EntityTreeElement;
|
||||
|
||||
public:
|
||||
enum EntityDirtyFlags {
|
||||
DIRTY_POSITION = 0x0001,
|
||||
|
@ -288,8 +291,15 @@ public:
|
|||
void setPhysicsInfo(void* data) { _physicsInfo = data; }
|
||||
|
||||
EntityTreeElement* getElement() const { return _element; }
|
||||
|
||||
static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; }
|
||||
static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
static bool _sendPhysicsUpdates;
|
||||
|
||||
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
||||
virtual void recalculateCollisionShape();
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "LightEntityItem.h"
|
||||
#include "ModelEntityItem.h"
|
||||
|
||||
|
||||
EntityScriptingInterface::EntityScriptingInterface() :
|
||||
_nextCreatorTokenID(0),
|
||||
_entityTree(NULL)
|
||||
|
@ -234,6 +235,14 @@ bool EntityScriptingInterface::getLightsArePickable() const {
|
|||
return LightEntityItem::getLightsArePickable();
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::setSendPhysicsUpdates(bool value) {
|
||||
EntityItem::setSendPhysicsUpdates(value);
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::getSendPhysicsUpdates() const {
|
||||
return EntityItem::getSendPhysicsUpdates();
|
||||
}
|
||||
|
||||
|
||||
RayToEntityIntersectionResult::RayToEntityIntersectionResult() :
|
||||
intersects(false),
|
||||
|
|
|
@ -99,6 +99,9 @@ public slots:
|
|||
Q_INVOKABLE void setLightsArePickable(bool value);
|
||||
Q_INVOKABLE bool getLightsArePickable() const;
|
||||
|
||||
Q_INVOKABLE void setSendPhysicsUpdates(bool value);
|
||||
Q_INVOKABLE bool getSendPhysicsUpdates() const;
|
||||
|
||||
Q_INVOKABLE void dumpTree() const;
|
||||
|
||||
signals:
|
||||
|
|
|
@ -132,3 +132,14 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SphereEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qDebug() << "SHPERE EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qDebug() << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
|
||||
qDebug() << " position:" << debugTreeVector(_position);
|
||||
qDebug() << " dimensions:" << debugTreeVector(_dimensions);
|
||||
qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@ public:
|
|||
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||
void** intersectedObject, bool precisionPicking) const;
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
protected:
|
||||
virtual void recalculateCollisionShape();
|
||||
|
||||
|
|
|
@ -97,8 +97,18 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
// DANGER! EntityItem stores angularVelocity in degrees/sec!!!
|
||||
_entity->setAngularVelocity(glm::degrees(v));
|
||||
|
||||
_entity->setLastSimulated(usecTimestampNow());
|
||||
|
||||
_outgoingPacketFlags = DIRTY_PHYSICS_FLAGS;
|
||||
EntityMotionState::enqueueOutgoingEntity(_entity);
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
quint64 now = usecTimestampNow();
|
||||
qDebug() << "EntityMotionState::setWorldTransform()... changed entity:" << _entity->getEntityItemID();
|
||||
qDebug() << " last edited:" << _entity->getLastEdited() << formatUsecTime(now - _entity->getLastEdited()) << "ago";
|
||||
qDebug() << " last simulated:" << _entity->getLastSimulated() << formatUsecTime(now - _entity->getLastSimulated()) << "ago";
|
||||
qDebug() << " last updated:" << _entity->getLastUpdated() << formatUsecTime(now - _entity->getLastUpdated()) << "ago";
|
||||
#endif
|
||||
}
|
||||
|
||||
void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t frame) {
|
||||
|
@ -221,13 +231,30 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
|
|||
quint64 lastSimulated = _entity->getLastSimulated();
|
||||
_entity->setLastEdited(lastSimulated);
|
||||
properties.setLastEdited(lastSimulated);
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
quint64 now = usecTimestampNow();
|
||||
qDebug() << "EntityMotionState::sendUpdate()";
|
||||
qDebug() << " EntityItemId:" << _entity->getEntityItemID() << "---------------------------------------------";
|
||||
qDebug() << " lastSimulated:" << debugTime(lastSimulated, now);
|
||||
#endif //def WANT_DEBUG
|
||||
|
||||
} else {
|
||||
properties.setLastEdited(_entity->getLastEdited());
|
||||
}
|
||||
|
||||
EntityItemID id(_entity->getID());
|
||||
EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender);
|
||||
entityPacketSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, id, properties);
|
||||
if (EntityItem::getSendPhysicsUpdates()) {
|
||||
EntityItemID id(_entity->getID());
|
||||
EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender);
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "EntityMotionState::sendUpdate()... calling queueEditEntityMessage()...";
|
||||
#endif
|
||||
entityPacketSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, id, properties);
|
||||
} else {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "EntityMotionState::sendUpdate()... NOT sending update as requested.";
|
||||
#endif
|
||||
}
|
||||
|
||||
// The outgoing flags only itemized WHAT to send, not WHETHER to send, hence we always set them
|
||||
// to the full set. These flags may be momentarily cleared by incoming external changes.
|
||||
|
|
|
@ -111,6 +111,12 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) {
|
|||
_sentFrame = simulationFrame;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
glm::vec3 wasPosition = _sentPosition;
|
||||
glm::quat wasRotation = _sentRotation;
|
||||
glm::vec3 wasAngularVelocity = _sentAngularVelocity;
|
||||
#endif
|
||||
|
||||
float dt = (float)(simulationFrame - _sentFrame) * PHYSICS_ENGINE_FIXED_SUBSTEP;
|
||||
_sentFrame = simulationFrame;
|
||||
|
@ -147,11 +153,21 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) {
|
|||
glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
|
||||
|
||||
float dx2 = glm::distance2(position, _sentPosition);
|
||||
|
||||
const float MAX_POSITION_ERROR_SQUARED = 0.001f; // 0.001 m^2 ~~> 0.03 m
|
||||
if (dx2 > MAX_POSITION_ERROR_SQUARED) {
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << ".... (dx2 > MAX_POSITION_ERROR_SQUARED) ....";
|
||||
qDebug() << "wasPosition:" << wasPosition;
|
||||
qDebug() << "bullet position:" << position;
|
||||
qDebug() << "_sentPosition:" << _sentPosition;
|
||||
qDebug() << "dx2:" << dx2;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (glm::length2(_sentAngularVelocity) > 0.0f) {
|
||||
// compute rotation error
|
||||
_sentAngularVelocity *= powf(1.0f - _angularDamping, dt);
|
||||
|
@ -165,6 +181,23 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) {
|
|||
}
|
||||
const float MIN_ROTATION_DOT = 0.98f;
|
||||
glm::quat actualRotation = bulletToGLM(worldTrans.getRotation());
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
if ((fabsf(glm::dot(actualRotation, _sentRotation)) < MIN_ROTATION_DOT)) {
|
||||
qDebug() << ".... ((fabsf(glm::dot(actualRotation, _sentRotation)) < MIN_ROTATION_DOT)) ....";
|
||||
|
||||
qDebug() << "wasAngularVelocity:" << wasAngularVelocity;
|
||||
qDebug() << "_sentAngularVelocity:" << _sentAngularVelocity;
|
||||
|
||||
qDebug() << "length wasAngularVelocity:" << glm::length(wasAngularVelocity);
|
||||
qDebug() << "length _sentAngularVelocity:" << glm::length(_sentAngularVelocity);
|
||||
|
||||
qDebug() << "wasRotation:" << wasRotation;
|
||||
qDebug() << "bullet actualRotation:" << actualRotation;
|
||||
qDebug() << "_sentRotation:" << _sentRotation;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (fabsf(glm::dot(actualRotation, _sentRotation)) < MIN_ROTATION_DOT);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue