Merge branch 'master' of https://github.com/highfidelity/hifi into 20397

This commit is contained in:
Stojce Slavkovski 2015-03-30 21:23:23 +02:00
commit eb46a4b647
44 changed files with 368 additions and 117 deletions

View file

@ -149,7 +149,8 @@ void AvatarMixer::broadcastAvatarData() {
// about a given otherNode to this node
// FIXME does this mean we should sort the othernodes by distance before iterating
// over them?
float outputBandwidth = node->getOutboundBandwidth();
// float outputBandwidth =
node->getOutboundBandwidth();
// this is an AGENT we have received head data from
// send back a packet with other active node data to this node
@ -169,7 +170,7 @@ void AvatarMixer::broadcastAvatarData() {
return true;
},
[&](const SharedNodePointer& otherNode) {
AvatarMixerClientData* otherNodeData = otherNodeData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData());
AvatarMixerClientData* otherNodeData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData());
MutexTryLocker lock(otherNodeData->getMutex());
if (!lock.isLocked()) {
return;

View file

@ -718,13 +718,8 @@ function mouseClickEvent(event) {
var result = findClickedEntity(event);
if (result) {
var properties = Entities.getEntityProperties(result.entityID);
var data = {};
try {
data = JSON.parse(properties.attribution);
} catch (e) {
}
if (data.marketplaceID) {
propertyMenu.marketplaceID = data.marketplaceID;
if (properties.marketplaceID) {
propertyMenu.marketplaceID = properties.marketplaceID;
propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace");
} else {
propertyMenu.marketplaceID = null;

View file

@ -140,7 +140,6 @@
var elLifetime = document.getElementById("property-lifetime");
var elScriptURL = document.getElementById("property-script-url");
var elUserData = document.getElementById("property-user-data");
var elAttribution = document.getElementById("property-attribution");
var elBoxSections = document.querySelectorAll(".box-section");
var elBoxColorRed = document.getElementById("property-box-red");
@ -264,7 +263,6 @@
elLifetime.value = properties.lifetime;
elScriptURL.value = properties.script;
elUserData.value = properties.userData;
elAttribution.value = properties.attribution;
if (properties.type != "Box") {
for (var i = 0; i < elBoxSections.length; i++) {
@ -395,7 +393,6 @@
elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime'));
elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script'));
elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData'));
elAttribution.addEventListener('change', createEmitTextPropertyUpdateFunction('attribution'));
var boxColorChangeFunction = createEmitColorPropertyUpdateFunction(
'color', elBoxColorRed, elBoxColorGreen, elBoxColorBlue);
@ -630,13 +627,6 @@
</div>
</div>
<div class="property">
<div class="label">Attribution</div>
<div class="value">
<textarea id="property-attribution"></textarea>
</div>
</div>
<div class="box-section property">
<div class="label">Color</div>

View file

@ -92,11 +92,13 @@ var NotificationType = {
SNAPSHOT: 2,
WINDOW_RESIZE: 3,
LOD_WARNING: 4,
CONNECTION_REFUSED: 5,
properties: [
{ text: "Mute Toggle" },
{ text: "Snapshot" },
{ text: "Window Resize" },
{ text: "Level of Detail" }
{ text: "Level of Detail" },
{ text: "Connection Refused" }
],
getTypeFromMenuItem: function(menuItemName) {
if (menuItemName.substr(menuItemName.length - NOTIFICATION_MENU_ITEM_POST.length) !== NOTIFICATION_MENU_ITEM_POST) {
@ -501,6 +503,10 @@ function onMuteStateChanged() {
createNotification(muteString, NotificationType.MUTE_TOGGLE);
}
function onDomainConnectionRefused(reason) {
createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED );
}
// handles mouse clicks on buttons
function mousePressEvent(event) {
var pickRay,
@ -608,5 +614,6 @@ Controller.keyReleaseEvent.connect(keyReleaseEvent);
Script.update.connect(update);
Script.scriptEnding.connect(scriptEnding);
Menu.menuItemEvent.connect(menuItemEvent);
Window.domainConnectionRefused.connect(onDomainConnectionRefused);
setup();

View file

@ -297,7 +297,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_lastSendDownstreamAudioStats(usecTimestampNow()),
_isVSyncOn(true),
_aboutToQuit(false),
_notifiedPacketVersionMismatchThisDomain(false)
_notifiedPacketVersionMismatchThisDomain(false),
_domainConnectionRefusals(QList<QString>())
{
#ifdef Q_OS_WIN
installNativeEventFilter(&MyNativeEventFilter::getInstance());
@ -344,6 +345,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
// put the NodeList and datagram processing on the node thread
nodeList->moveToThread(nodeThread);
// geometry background downloads need to happen on the Datagram Processor Thread. The idle loop will
// emit checkBackgroundDownloads to cause the GeometryCache to check it's queue for requested background
// downloads.
QSharedPointer<GeometryCache> geometryCacheP = DependencyManager::get<GeometryCache>();
ResourceCache *geometryCache = geometryCacheP.data();
connect(this, &Application::checkBackgroundDownloads, geometryCache, &ResourceCache::checkAsynchronousGets);
// connect the DataProcessor processDatagrams slot to the QUDPSocket readyRead() signal
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _datagramProcessor, &DatagramProcessor::processDatagrams);
@ -1556,6 +1564,9 @@ void Application::idle() {
idleTimer->start(2);
}
}
// check for any requested background downloads.
emit checkBackgroundDownloads();
}
void Application::setFullscreen(bool fullscreen) {
@ -3125,7 +3136,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
bool eyeRelativeCamera = false;
// bool eyeRelativeCamera = false;
if (billboard) {
_mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW); // degees
_mirrorCamera.setPosition(_myAvatar->getPosition() +
@ -3278,6 +3289,14 @@ void Application::clearDomainOctreeDetails() {
void Application::domainChanged(const QString& domainHostname) {
updateWindowTitle();
clearDomainOctreeDetails();
_domainConnectionRefusals.clear();
}
void Application::domainConnectionDenied(const QString& reason) {
if (!_domainConnectionRefusals.contains(reason)) {
_domainConnectionRefusals.append(reason);
emit domainConnectionRefused(reason);
}
}
void Application::connectedToDomain(const QString& hostname) {

View file

@ -333,6 +333,9 @@ signals:
void svoImportRequested(const QString& url);
void checkBackgroundDownloads();
void domainConnectionRefused(const QString& reason);
public slots:
void domainChanged(const QString& domainHostname);
void updateWindowTitle();
@ -383,6 +386,8 @@ public slots:
void setActiveFaceTracker();
void domainConnectionDenied(const QString& reason);
private slots:
void clearDomainOctreeDetails();
void checkFPS();
@ -607,6 +612,8 @@ private:
int _menuBarHeight;
QHash<QString, AcceptURLMethod> _acceptedExtensions;
QList<QString> _domainConnectionRefusals;
};
#endif // hifi_Application_h

View file

@ -127,6 +127,7 @@ void DatagramProcessor::processDatagrams() {
// and check and signal for an access token so that we can make sure they are logged in
qDebug() << "The domain-server denied a connection request: " << reason;
qDebug() << "You may need to re-log to generate a keypair so you can provide a username signature.";
application->domainConnectionDenied(reason);
AccountManager::getInstance().checkAndSignalForAccessToken();
break;
}

View file

@ -353,7 +353,7 @@ void InputController::update() {
// TODO for now the InputController is only supporting a JointTracker from a MotionTracker
MotionTracker* motionTracker = dynamic_cast< MotionTracker*> (DeviceTracker::getDevice(_deviceTrackerId));
if (motionTracker) {
if (_subTrackerId < motionTracker->numJointTrackers()) {
if ((int)_subTrackerId < motionTracker->numJointTrackers()) {
const MotionTracker::JointTracker* joint = motionTracker->getJointTracker(_subTrackerId);
if (joint->isActive()) {

View file

@ -33,6 +33,7 @@ WindowScriptingInterface::WindowScriptingInterface() :
const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
connect(&domainHandler, &DomainHandler::hostnameChanged, this, &WindowScriptingInterface::domainChanged);
connect(Application::getInstance(), &Application::svoImportRequested, this, &WindowScriptingInterface::svoImportRequested);
connect(Application::getInstance(), &Application::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);
}
WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height, bool isToolWindow) {

View file

@ -62,6 +62,7 @@ signals:
void inlineButtonClicked(const QString& name);
void nonBlockingFormClosed();
void svoImportRequested(const QString& url);
void domainConnectionRefused(const QString& reason);
private slots:
QScriptValue showAlert(const QString& message);

View file

@ -139,6 +139,7 @@ ApplicationOverlay::ApplicationOverlay() :
_magnifier(true),
_alpha(1.0f),
_oculusUIRadius(1.0f),
_trailingAudioLoudness(0.0f),
_crosshairTexture(0),
_previousBorderWidth(-1),
_previousBorderHeight(-1),

View file

@ -88,9 +88,9 @@ template< typename T >
void AudioFrameBuffer< T >::deallocateFrames() {
if (_frameBuffer) {
for (uint32_t i = 0; i < _channelCountMax; ++i) {
delete _frameBuffer[i];
delete[] _frameBuffer[i];
}
delete _frameBuffer;
delete[] _frameBuffer;
}
_frameBuffer = NULL;
}

View file

@ -88,7 +88,7 @@ public:
}
void loadProfile(int profileIndex) {
if (profileIndex >= 0 && profileIndex < _profileCount) {
if (profileIndex >= 0 && profileIndex < (int)_profileCount) {
for (uint32_t i = 0; i < _filterCount; ++i) {
FilterParameter p = _profiles[profileIndex][i];

View file

@ -266,6 +266,26 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking);
}
void RenderableModelEntityItem::setCollisionModelURL(const QString& url) {
ModelEntityItem::setCollisionModelURL(url);
if (_model) {
_model->setCollisionModelURL(QUrl(url));
}
}
bool RenderableModelEntityItem::hasCollisionModel() const {
if (_model) {
return ! _model->getCollisionURL().isEmpty();
} else {
return !_collisionModelURL.isEmpty();
}
}
const QString& RenderableModelEntityItem::getCollisionModelURL() const {
assert (!_model || _collisionModelURL == _model->getCollisionURL().toString());
return _collisionModelURL;
}
bool RenderableModelEntityItem::isReadyToComputeShape() {
if (!_model) {
@ -294,13 +314,67 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry();
AABox aaBox;
_points.clear();
unsigned int i = 0;
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
_points << mesh.vertices;
foreach (const FBXMeshPart &meshPart, mesh.parts) {
QVector<glm::vec3> pointsInPart;
unsigned int triangleCount = meshPart.triangleIndices.size() / 3;
assert((unsigned int)meshPart.triangleIndices.size() == triangleCount*3);
for (unsigned int j = 0; j < triangleCount; j++) {
unsigned int p0Index = meshPart.triangleIndices[j*3];
unsigned int p1Index = meshPart.triangleIndices[j*3+1];
unsigned int p2Index = meshPart.triangleIndices[j*3+2];
assert(p0Index < (unsigned int)mesh.vertices.size());
assert(p1Index < (unsigned int)mesh.vertices.size());
assert(p2Index < (unsigned int)mesh.vertices.size());
glm::vec3 p0 = mesh.vertices[p0Index];
glm::vec3 p1 = mesh.vertices[p1Index];
glm::vec3 p2 = mesh.vertices[p2Index];
aaBox += p0;
aaBox += p1;
aaBox += p2;
if (!pointsInPart.contains(p0)) {
pointsInPart << p0;
}
if (!pointsInPart.contains(p1)) {
pointsInPart << p1;
}
if (!pointsInPart.contains(p2)) {
pointsInPart << p2;
}
}
QVector<glm::vec3> newMeshPoints;
_points << newMeshPoints;
_points[i++] << pointsInPart;
}
}
info.setParams(getShapeType(), 0.5f * getDimensions(), _collisionModelURL);
info.setConvexHull(_points);
// make sure we aren't about to divide by zero
glm::vec3 aaBoxDim = aaBox.getDimensions();
aaBoxDim = glm::clamp(aaBoxDim, glm::vec3(FLT_EPSILON), aaBoxDim);
glm::vec3 scale = _dimensions / aaBoxDim;
// multiply each point by scale before handing the point-set off to the physics engine
for (int i = 0; i < _points.size(); i++) {
for (int j = 0; j < _points[i].size(); j++) {
// compensate for registraion
_points[i][j] += _model->getOffset();
// scale so the collision points match the model points
_points[i][j] *= scale;
}
}
info.setParams(getShapeType(), _dimensions, _collisionModelURL);
info.setConvexHulls(_points);
}
}
@ -308,7 +382,9 @@ ShapeType RenderableModelEntityItem::getShapeType() const {
// XXX make hull an option in edit.js ?
if (!_model || _model->getCollisionURL().isEmpty()) {
return _shapeType;
} else {
} else if (_points.size() == 1) {
return SHAPE_TYPE_CONVEX_HULL;
} else {
return SHAPE_TYPE_COMPOUND;
}
}

View file

@ -52,6 +52,10 @@ public:
bool needsToCallUpdate() const;
virtual void setCollisionModelURL(const QString& url);
virtual bool hasCollisionModel() const;
virtual const QString& getCollisionModelURL() const;
bool isReadyToComputeShape();
void computeShapeInfo(ShapeInfo& info);
ShapeType getShapeType() const;
@ -66,7 +70,7 @@ private:
QString _currentTextures;
QStringList _originalTextures;
bool _originalTexturesRead;
QVector<glm::vec3> _points;
QVector<QVector<glm::vec3>> _points;
};
#endif // hifi_RenderableModelEntityItem_h

View file

@ -57,7 +57,7 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
_collisionsWillMove = ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE;
_locked = ENTITY_ITEM_DEFAULT_LOCKED;
_userData = ENTITY_ITEM_DEFAULT_USER_DATA;
_attribution = ENTITY_ITEM_DEFAULT_ATTRIBUTION;
_marketplaceID = ENTITY_ITEM_DEFAULT_MARKETPLACE_ID;
}
EntityItem::EntityItem(const EntityItemID& entityItemID) {
@ -117,7 +117,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
requestedProperties += PROP_COLLISIONS_WILL_MOVE;
requestedProperties += PROP_LOCKED;
requestedProperties += PROP_USER_DATA;
requestedProperties += PROP_ATTRIBUTION;
requestedProperties += PROP_MARKETPLACE_ID;
return requestedProperties;
}
@ -240,7 +240,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove());
APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, getLocked());
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData());
APPEND_ENTITY_PROPERTY(PROP_ATTRIBUTION, appendValue, getAttribution());
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, getMarketplaceID());
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
requestedProperties,
@ -555,8 +555,8 @@ 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 (args.bitstreamVersion >= VERSION_ENTITIES_HAS_ATTRIBUTION) {
READ_ENTITY_PROPERTY_STRING(PROP_ATTRIBUTION, setAttribution);
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) {
READ_ENTITY_PROPERTY_STRING(PROP_MARKETPLACE_ID, setMarketplaceID);
}
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData);
@ -568,8 +568,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
// by doing this parsing here... but it's not likely going to fully recover the content.
//
// TODO: Remove this conde once we've sufficiently migrated content past this damaged version
if (args.bitstreamVersion == VERSION_ENTITIES_HAS_ATTRIBUTION_DAMAGED) {
READ_ENTITY_PROPERTY_STRING(PROP_ATTRIBUTION, setAttribution);
if (args.bitstreamVersion == VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED) {
READ_ENTITY_PROPERTY_STRING(PROP_MARKETPLACE_ID, setMarketplaceID);
}
if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY))) {
@ -838,7 +838,7 @@ EntityItemProperties EntityItem::getProperties() const {
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionsWillMove, getCollisionsWillMove);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(attribution, getAttribution);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(marketplaceID, getMarketplaceID);
properties._defaultSettings = false;
@ -867,7 +867,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(attribution, setAttribution);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(marketplaceID, setMarketplaceID);
if (somethingChanged) {
somethingChangedNotification(); // notify derived classes that something has changed

View file

@ -251,8 +251,8 @@ public:
const QString& getUserData() const { return _userData; }
void setUserData(const QString& value) { _userData = value; }
const QString& getAttribution() const { return _attribution; }
void setAttribution(const QString& value) { _attribution = value; }
const QString& getMarketplaceID() const { return _marketplaceID; }
void setMarketplaceID(const QString& value) { _marketplaceID = value; }
// TODO: get rid of users of getRadius()...
float getRadius() const;
@ -342,7 +342,7 @@ protected:
bool _collisionsWillMove;
bool _locked;
QString _userData;
QString _attribution;
QString _marketplaceID;
// NOTE: Damping is applied like this: v *= pow(1 - damping, dt)
//

View file

@ -70,7 +70,7 @@ EntityItemProperties::EntityItemProperties() :
CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH),
CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY),
CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS),
CONSTRUCT_PROPERTY(attribution, ENTITY_ITEM_DEFAULT_ATTRIBUTION),
CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID),
_id(UNKNOWN_ENTITY_ID),
_idSet(false),
@ -260,7 +260,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_EMIT_STRENGTH, emitStrength);
CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity);
CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius);
CHECK_PROPERTY_CHANGE(PROP_ATTRIBUTION, attribution);
CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID);
return changedProperties;
}
@ -323,7 +323,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength);
COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity);
COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius);
COPY_PROPERTY_TO_QSCRIPTVALUE(attribution);
COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID);
// Sitting properties support
QScriptValue sittingPoints = engine->newObject();
@ -405,7 +405,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitStrength, setEmitStrength);
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localGravity, setLocalGravity);
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius);
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(attribution, setAttribution);
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(marketplaceID, setMarketplaceID);
_lastEdited = usecTimestampNow();
}
@ -591,7 +591,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, properties.getParticleRadius());
}
APPEND_ENTITY_PROPERTY(PROP_ATTRIBUTION, appendValue, properties.getAttribution());
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID());
}
if (propertyCount > 0) {
int endOfEntityItemData = packetData->getUncompressedByteOffset();
@ -822,7 +822,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius);
}
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ATTRIBUTION, setAttribution);
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID);
return valid;
}
@ -905,7 +905,7 @@ void EntityItemProperties::markAllChanged() {
_localGravityChanged = true;
_particleRadiusChanged = true;
_attributionChanged = true;
_marketplaceIDChanged = true;
}
/// The maximum bounding cube for the entity, independent of it's rotation.

View file

@ -94,11 +94,11 @@ enum EntityPropertyList {
PROP_PARTICLE_RADIUS,
PROP_COLLISION_MODEL_URL,
PROP_ATTRIBUTION,
PROP_MARKETPLACE_ID,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties ABOVE this line and then modify PROP_LAST_ITEM below
PROP_LAST_ITEM = PROP_ATTRIBUTION,
PROP_LAST_ITEM = PROP_MARKETPLACE_ID,
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -205,7 +205,7 @@ public:
DEFINE_PROPERTY(PROP_EMIT_STRENGTH, EmitStrength, emitStrength, float);
DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float);
DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float);
DEFINE_PROPERTY_REF(PROP_ATTRIBUTION, Attribution, attribution, QString);
DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString);
public:
float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); }
@ -333,7 +333,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Attribution, attribution, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, "");
debug << " last edited:" << properties.getLastEdited() << "\n";
debug << " edited ago:" << properties.getEditedAgo() << "\n";

View file

@ -22,7 +22,7 @@ const glm::vec3 ENTITY_ITEM_ZERO_VEC3(0.0f);
const bool ENTITY_ITEM_DEFAULT_LOCKED = false;
const QString ENTITY_ITEM_DEFAULT_USER_DATA = QString("");
const QString ENTITY_ITEM_DEFAULT_ATTRIBUTION = QString("");
const QString ENTITY_ITEM_DEFAULT_MARKETPLACE_ID = QString("");
const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f;

View file

@ -95,7 +95,6 @@ public:
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = false);
void deleteEntities(QSet<EntityItemID> entityIDs, bool force = false, bool ignoreWarnings = false);
void removeEntityFromSimulation(EntityItem* entity);
/// \param position point of query in world-frame (meters)
/// \param targetRadius radius of query (meters)

View file

@ -281,6 +281,13 @@ void ModelEntityItem::updateShapeType(ShapeType type) {
}
}
void ModelEntityItem::setCollisionModelURL(const QString& url) {
if (_collisionModelURL != url) {
_collisionModelURL = url;
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
}
}
void ModelEntityItem::setAnimationURL(const QString& url) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationURL = url;

View file

@ -57,13 +57,13 @@ public:
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
bool hasModel() const { return !_modelURL.isEmpty(); }
bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); }
virtual bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); }
static const QString DEFAULT_MODEL_URL;
const QString& getModelURL() const { return _modelURL; }
static const QString DEFAULT_COLLISION_MODEL_URL;
const QString& getCollisionModelURL() const { return _collisionModelURL; }
virtual const QString& getCollisionModelURL() const { return _collisionModelURL; }
bool hasAnimation() const { return !_animationURL.isEmpty(); }
static const QString DEFAULT_ANIMATION_URL;
@ -78,7 +78,7 @@ public:
// model related properties
void setModelURL(const QString& url) { _modelURL = url; }
void setCollisionModelURL(const QString& url) { _collisionModelURL = url; }
virtual void setCollisionModelURL(const QString& url);
void setAnimationURL(const QString& url);
static const float DEFAULT_ANIMATION_FRAME_INDEX;
void setAnimationFrameIndex(float value);

View file

@ -249,7 +249,20 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
} else if (indices.count() == 4) {
meshPart.quadIndices << indices;
} else {
qDebug() << "no support for more than 4 vertices on a face in OBJ files";
// some obj writers (maya) will write a face with lots of points.
for (int i = 1; i < indices.count() - 1; i++) {
// break the face into triangles
meshPart.triangleIndices.append(indices[0]);
meshPart.triangleIndices.append(indices[i]);
meshPart.triangleIndices.append(indices[i+1]);
}
if (indices.count() == normalIndices.count()) {
for (int i = 1; i < normalIndices.count() - 1; i++) {
faceNormalIndexes.append(normalIndices[0]);
faceNormalIndexes.append(normalIndices[i]);
faceNormalIndexes.append(normalIndices[i+1]);
}
}
}
} else {
// something we don't (yet) care about

View file

@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) {
return 1;
case PacketTypeEntityAddOrEdit:
case PacketTypeEntityData:
return VERSION_ENTITIES_HAS_ATTRIBUTION;
return VERSION_ENTITIES_HAS_MARKETPLACE_ID;
case PacketTypeEntityErase:
return 2;
case PacketTypeAudioStreamStats:

View file

@ -132,8 +132,8 @@ const PacketVersion VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES =
const PacketVersion VERSION_ENTITIES_HAS_PARTICLES = 10;
const PacketVersion VERSION_ENTITIES_USE_METERS_AND_RADIANS = 11;
const PacketVersion VERSION_ENTITIES_HAS_COLLISION_MODEL = 12;
const PacketVersion VERSION_ENTITIES_HAS_ATTRIBUTION_DAMAGED = 13;
const PacketVersion VERSION_ENTITIES_HAS_ATTRIBUTION = 14;
const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED = 13;
const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID = 14;
const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1;
#endif // hifi_PacketHeaders_h

View file

@ -18,6 +18,7 @@
#include <QTimer>
#include <SharedUtil.h>
#include <assert.h>
#include "NetworkAccessManager.h"
#include "ResourceCache.h"
@ -48,32 +49,40 @@ void ResourceCache::refresh(const QUrl& url) {
}
}
void ResourceCache::getResourceAsynchronously(const QUrl& url) {
qDebug() << "ResourceCache::getResourceAsynchronously" << url.toString();
_resourcesToBeGottenLock.lockForWrite();
_resourcesToBeGotten.enqueue(QUrl(url));
_resourcesToBeGottenLock.unlock();
}
void ResourceCache::checkAsynchronousGets() {
assert(QThread::currentThread() == thread());
if (!_resourcesToBeGotten.isEmpty()) {
_resourcesToBeGottenLock.lockForWrite();
QUrl url = _resourcesToBeGotten.dequeue();
_resourcesToBeGottenLock.unlock();
getResource(url);
}
}
QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl& fallback,
bool delayLoad, void* extra, bool block) {
bool delayLoad, void* extra) {
QSharedPointer<Resource> resource = _resources.value(url);
if (!resource.isNull()) {
return resource;
}
if (QThread::currentThread() != thread()) {
// This will re-call this method in the main thread. If block is true and the main thread
// is waiting on a lock, we'll deadlock here.
if (block) {
QSharedPointer<Resource> result;
QMetaObject::invokeMethod(this, "getResource", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QSharedPointer<Resource>, result), Q_ARG(const QUrl&, url),
Q_ARG(const QUrl&, fallback), Q_ARG(bool, delayLoad), Q_ARG(void*, extra));
return result;
} else {
// Queue the re-invocation of this method, but if the main thread is blocked, don't wait. The
// return value may be NULL -- it's expected that this will be called again later, in order
// to receive the actual Resource.
QMetaObject::invokeMethod(this, "getResource", Qt::QueuedConnection,
Q_ARG(const QUrl&, url),
Q_ARG(const QUrl&, fallback), Q_ARG(bool, delayLoad), Q_ARG(void*, extra));
return _resources.value(url);
}
assert(delayLoad);
getResourceAsynchronously(url);
return QSharedPointer<Resource>();
}
if (!url.isValid() && !url.isEmpty() && fallback.isValid()) {
return getResource(fallback, QUrl(), delayLoad);
}
QSharedPointer<Resource> resource = _resources.value(url);
if (resource.isNull()) {
resource = createResource(url, fallback.isValid() ?
getResource(fallback, QUrl(), true) : QSharedPointer<Resource>(), delayLoad, extra);

View file

@ -21,6 +21,8 @@
#include <QSharedPointer>
#include <QUrl>
#include <QWeakPointer>
#include <QReadWriteLock>
#include <QQueue>
#include <DependencyManager.h>
@ -79,6 +81,9 @@ public:
void refresh(const QUrl& url);
public slots:
void checkAsynchronousGets();
protected:
qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE;
qint64 _unusedResourcesSize = 0;
@ -89,7 +94,7 @@ protected:
/// \param delayLoad if true, don't load the resource immediately; wait until load is first requested
/// \param extra extra data to pass to the creator, if appropriate
Q_INVOKABLE QSharedPointer<Resource> getResource(const QUrl& url, const QUrl& fallback = QUrl(),
bool delayLoad = false, void* extra = NULL, bool block = true);
bool delayLoad = false, void* extra = NULL);
/// Creates a new resource.
virtual QSharedPointer<Resource> createResource(const QUrl& url,
@ -109,6 +114,11 @@ private:
int _lastLRUKey = 0;
static int _requestLimit;
void getResourceAsynchronously(const QUrl& url);
QReadWriteLock _resourcesToBeGottenLock;
QQueue<QUrl> _resourcesToBeGotten;
};
/// Base class for resources.

View file

@ -235,7 +235,9 @@ CharacterController::CharacterController(AvatarData* avatarData) {
_jumpToHoverStart = 0;
setMaxSlope(btRadians(45.0f));
_lastStepUp = 0.0f;
_pendingFlags = 0;
_pendingFlags = PENDING_FLAG_UPDATE_SHAPE;
updateShapeIfNecessary();
}
CharacterController::~CharacterController() {
@ -786,14 +788,17 @@ void CharacterController::setEnabled(bool enabled) {
void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
if (_dynamicsWorld != world) {
if (_dynamicsWorld) {
_dynamicsWorld->removeCollisionObject(getGhostObject());
_dynamicsWorld->removeAction(this);
if (_dynamicsWorld) {
if (_ghostObject) {
_dynamicsWorld->removeCollisionObject(_ghostObject);
_dynamicsWorld->removeAction(this);
}
_dynamicsWorld = NULL;
}
_dynamicsWorld = world;
if (_dynamicsWorld) {
if (world && _ghostObject) {
_dynamicsWorld = world;
_pendingFlags &= ~ PENDING_FLAG_JUMP;
_dynamicsWorld->addCollisionObject(getGhostObject(),
_dynamicsWorld->addCollisionObject(_ghostObject,
btBroadphaseProxy::CharacterFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
_dynamicsWorld->addAction(this);
@ -876,7 +881,7 @@ void CharacterController::preSimulation(btScalar timeStep) {
}
void CharacterController::postSimulation() {
if (_enabled) {
if (_enabled && _ghostObject) {
const btTransform& avatarTransform = _ghostObject->getWorldTransform();
glm::quat rotation = bulletToGLM(avatarTransform.getRotation());
glm::vec3 position = bulletToGLM(avatarTransform.getOrigin());

View file

@ -169,7 +169,9 @@ void EntityMotionState::updateObjectVelocities() {
}
void EntityMotionState::computeShapeInfo(ShapeInfo& shapeInfo) {
_entity->computeShapeInfo(shapeInfo);
if (_entity->isReadyToComputeShape()) {
_entity->computeShapeInfo(shapeInfo);
}
}
float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const {

View file

@ -29,6 +29,12 @@ PhysicsEngine::PhysicsEngine(const glm::vec3& offset)
PhysicsEngine::~PhysicsEngine() {
// TODO: delete engine components... if we ever plan to create more than one instance
delete _collisionConfig;
delete _collisionDispatcher;
delete _broadphaseFilter;
delete _constraintSolver;
delete _dynamicsWorld;
// delete _ghostPairCallback;
}
// begin EntitySimulation overrides

View file

@ -29,6 +29,9 @@ int ShapeInfoUtil::toBulletShapeType(int shapeInfoType) {
case SHAPE_TYPE_CONVEX_HULL:
bulletShapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
break;
case SHAPE_TYPE_COMPOUND:
bulletShapeType = COMPOUND_SHAPE_PROXYTYPE;
break;
}
return bulletShapeType;
}
@ -48,6 +51,9 @@ int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) {
case CONVEX_HULL_SHAPE_PROXYTYPE:
shapeInfoType = SHAPE_TYPE_CONVEX_HULL;
break;
case COMPOUND_SHAPE_PROXYTYPE:
shapeInfoType = SHAPE_TYPE_COMPOUND;
break;
}
return shapeInfoType;
}
@ -70,12 +76,34 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf
const btConvexHullShape* convexHullShape = static_cast<const btConvexHullShape*>(shape);
const int numPoints = convexHullShape->getNumPoints();
const btVector3* btPoints = convexHullShape->getUnscaledPoints();
QVector<glm::vec3> points;
QVector<QVector<glm::vec3>> points;
QVector<glm::vec3> childPoints;
for (int i = 0; i < numPoints; i++) {
glm::vec3 point(btPoints->getX(), btPoints->getY(), btPoints->getZ());
points << point;
childPoints << point;
}
info.setConvexHull(points);
points << childPoints;
info.setConvexHulls(points);
}
break;
case SHAPE_TYPE_COMPOUND: {
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
const int numChildShapes = compoundShape->getNumChildShapes();
QVector<QVector<glm::vec3>> points;
for (int i = 0; i < numChildShapes; i ++) {
const btCollisionShape* childShape = compoundShape->getChildShape(i);
const btConvexHullShape* convexHullShape = static_cast<const btConvexHullShape*>(childShape);
const int numPoints = convexHullShape->getNumPoints();
const btVector3* btPoints = convexHullShape->getUnscaledPoints();
QVector<glm::vec3> childPoints;
for (int j = 0; j < numPoints; j++) {
glm::vec3 point(btPoints->getX(), btPoints->getY(), btPoints->getZ());
childPoints << point;
}
points << childPoints;
}
info.setConvexHulls(points);
}
break;
default: {
@ -108,12 +136,32 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
}
break;
case SHAPE_TYPE_CONVEX_HULL: {
shape = new btConvexHullShape();
const QVector<glm::vec3>& points = info.getPoints();
foreach (glm::vec3 point, points) {
auto hull = new btConvexHullShape();
const QVector<QVector<glm::vec3>>& points = info.getPoints();
foreach (glm::vec3 point, points[0]) {
btVector3 btPoint(point[0], point[1], point[2]);
static_cast<btConvexHullShape*>(shape)->addPoint(btPoint);
hull->addPoint(btPoint, false);
}
hull->recalcLocalAabb();
shape = hull;
}
break;
case SHAPE_TYPE_COMPOUND: {
auto compound = new btCompoundShape();
const QVector<QVector<glm::vec3>>& points = info.getPoints();
btTransform trans;
trans.setIdentity();
foreach (QVector<glm::vec3> hullPoints, points) {
auto hull = new btConvexHullShape();
foreach (glm::vec3 point, hullPoints) {
btVector3 btPoint(point[0], point[1], point[2]);
hull->addPoint(btPoint, false);
}
hull->recalcLocalAabb();
compound->addChildShape (trans, hull);
}
shape = compound;
}
break;
}

View file

@ -20,6 +20,8 @@
// translates between ShapeInfo and btShape
namespace ShapeInfoUtil {
// XXX is collectInfoFromShape no longer strictly needed?
void collectInfoFromShape(const btCollisionShape* shape, ShapeInfo& info);
btCollisionShape* createShapeFromInfo(const ShapeInfo& info);

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QDebug>
#include <glm/gtx/norm.hpp>
#include "ShapeInfoUtil.h"
@ -35,6 +37,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) {
const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube
const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e4f; // 100 m cube
if (diagonal < MIN_SHAPE_DIAGONAL_SQUARED || diagonal > MAX_SHAPE_DIAGONAL_SQUARED) {
// qDebug() << "ShapeManager::getShape -- not making shape due to size" << diagonal;
return NULL;
}
DoubleHashKey key = info.getHash();
@ -100,6 +103,18 @@ void ShapeManager::collectGarbage() {
DoubleHashKey& key = _pendingGarbage[i];
ShapeReference* shapeRef = _shapeMap.find(key);
if (shapeRef && shapeRef->refCount == 0) {
// if the shape we're about to delete is compound, delete the children first.
auto shapeType = ShapeInfoUtil::fromBulletShapeType(shapeRef->shape->getShapeType());
if (shapeType == SHAPE_TYPE_COMPOUND) {
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shapeRef->shape);
const int numChildShapes = compoundShape->getNumChildShapes();
QVector<QVector<glm::vec3>> points;
for (int i = 0; i < numChildShapes; i ++) {
const btCollisionShape* childShape = compoundShape->getChildShape(i);
delete childShape;
}
}
delete shapeRef->shape;
_shapeMap.remove(key);
}

View file

@ -134,7 +134,7 @@ void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radi
void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color,
float intensity, const glm::quat& orientation, float exponent, float cutoff) {
int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();
unsigned int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();
if (lightID >= _allocatedLights.size()) {
_allocatedLights.push_back(model::LightPointer(new model::Light()));
}

View file

@ -1771,8 +1771,8 @@ void GeometryCache::renderLine(const glm::vec2& p1, const glm::vec2& p2,
}
QSharedPointer<NetworkGeometry> GeometryCache::getGeometry(const QUrl& url, const QUrl& fallback, bool delayLoad, bool block) {
return getResource(url, fallback, delayLoad, NULL, block).staticCast<NetworkGeometry>();
QSharedPointer<NetworkGeometry> GeometryCache::getGeometry(const QUrl& url, const QUrl& fallback, bool delayLoad) {
return getResource(url, fallback, delayLoad, NULL).staticCast<NetworkGeometry>();
}
QSharedPointer<Resource> GeometryCache::createResource(const QUrl& url,

View file

@ -203,8 +203,7 @@ public:
/// Loads geometry from the specified URL.
/// \param fallback a fallback URL to load if the desired one is unavailable
/// \param delayLoad if true, don't load the geometry immediately; wait until load is first requested
QSharedPointer<NetworkGeometry> getGeometry(const QUrl& url, const QUrl& fallback = QUrl(),
bool delayLoad = false, bool block = true);
QSharedPointer<NetworkGeometry> getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false);
protected:

View file

@ -325,6 +325,8 @@ void Model::init() {
_skinTranslucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelTranslucentPixel));
makeResult = gpu::Shader::makeProgram(*_skinTranslucentProgram, slotBindings);
initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations);
(void) makeResult; // quiet compiler
}
}
@ -1032,12 +1034,22 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
}
}
void Model::setCollisionModelURL(const QUrl& url, const QUrl& fallback, bool delayLoad) {
const QSharedPointer<NetworkGeometry> Model::getCollisionGeometry(bool delayLoad)
{
if (_collisionGeometry.isNull() && !_collisionUrl.isEmpty()) {
_collisionGeometry = DependencyManager::get<GeometryCache>()->getGeometry(_collisionUrl, QUrl(), delayLoad);
}
return _collisionGeometry;
}
void Model::setCollisionModelURL(const QUrl& url) {
if (_collisionUrl == url) {
return;
}
_collisionUrl = url;
_collisionGeometry = DependencyManager::get<GeometryCache>()->getGeometry(url, fallback, delayLoad);
_collisionGeometry = DependencyManager::get<GeometryCache>()->getGeometry(url, QUrl(), true);
}
bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {

View file

@ -109,7 +109,7 @@ public:
const QUrl& getURL() const { return _url; }
// Set the model to use for collisions
Q_INVOKABLE void setCollisionModelURL(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false);
Q_INVOKABLE void setCollisionModelURL(const QUrl& url);
const QUrl& getCollisionURL() const { return _collisionUrl; }
/// Sets the distance parameter used for LOD computations.
@ -134,7 +134,7 @@ public:
const QSharedPointer<NetworkGeometry>& getGeometry() const { return _geometry; }
/// Returns a reference to the shared collision geometry.
const QSharedPointer<NetworkGeometry> getCollisionGeometry() {return _collisionGeometry; }
const QSharedPointer<NetworkGeometry> getCollisionGeometry(bool delayLoad = true);
/// Returns the number of joint states in the model.
int getJointStateCount() const { return _jointStates.size(); }

View file

@ -23,6 +23,7 @@ void ShapeInfo::clear() {
void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) {
_type = type;
_points.clear();
switch(type) {
case SHAPE_TYPE_NONE:
_halfExtents = glm::vec3(0.0f);
@ -37,6 +38,12 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
break;
}
case SHAPE_TYPE_CONVEX_HULL:
_url = QUrl(url);
// halfExtents aren't used by convex-hull or compound convex-hull except as part of
// the generation of the key for the ShapeManager.
_halfExtents = halfExtents;
break;
case SHAPE_TYPE_COMPOUND:
_url = QUrl(url);
_halfExtents = halfExtents;
break;
@ -47,31 +54,44 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
}
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
_url = "";
_type = SHAPE_TYPE_BOX;
_halfExtents = halfExtents;
_points.clear();
_doubleHashKey.clear();
}
void ShapeInfo::setSphere(float radius) {
_url = "";
_type = SHAPE_TYPE_SPHERE;
_halfExtents = glm::vec3(radius, radius, radius);
_points.clear();
_doubleHashKey.clear();
}
void ShapeInfo::setEllipsoid(const glm::vec3& halfExtents) {
_url = "";
_type = SHAPE_TYPE_ELLIPSOID;
_halfExtents = halfExtents;
_points.clear();
_doubleHashKey.clear();
}
void ShapeInfo::setConvexHull(const QVector<glm::vec3>& points) {
_type = SHAPE_TYPE_CONVEX_HULL;
void ShapeInfo::setConvexHulls(const QVector<QVector<glm::vec3>>& points) {
if (points.size() == 1) {
_type = SHAPE_TYPE_CONVEX_HULL;
} else {
_type = SHAPE_TYPE_COMPOUND;
}
_points = points;
_doubleHashKey.clear();
}
void ShapeInfo::setCapsuleY(float radius, float halfHeight) {
_url = "";
_type = SHAPE_TYPE_CAPSULE_Y;
_halfExtents = glm::vec3(radius, halfHeight, radius);
_points.clear();
_doubleHashKey.clear();
}

View file

@ -44,14 +44,14 @@ public:
void setBox(const glm::vec3& halfExtents);
void setSphere(float radius);
void setEllipsoid(const glm::vec3& halfExtents);
void setConvexHull(const QVector<glm::vec3>& points);
void setConvexHulls(const QVector<QVector<glm::vec3>>& points);
void setCapsuleY(float radius, float halfHeight);
const int getType() const { return _type; }
const glm::vec3& getHalfExtents() const { return _halfExtents; }
const QVector<glm::vec3>& getPoints() const { return _points; }
const QVector<QVector<glm::vec3>>& getPoints() const { return _points; }
void clearPoints () { _points.clear(); }
void appendToPoints (const QVector<glm::vec3>& newPoints) { _points << newPoints; }
@ -64,8 +64,8 @@ protected:
ShapeType _type = SHAPE_TYPE_NONE;
glm::vec3 _halfExtents = glm::vec3(0.0f);
DoubleHashKey _doubleHashKey;
QVector<glm::vec3> _points; // points for convex collision hull
QUrl _url; // url for model of convex collision hull
QVector<QVector<glm::vec3>> _points; // points for convex collision hulls
QUrl _url; // url for model of convex collision hulls
};
#endif // hifi_ShapeInfo_h

View file

@ -14,6 +14,7 @@
SimpleMovingAverage::SimpleMovingAverage(int numSamplesToAverage) :
_numSamples(0),
_lastEventTimestamp(0),
_average(0.0f),
_eventDeltaAverage(0.0f),
WEIGHTING(1.0f / numSamplesToAverage),

View file

@ -8,5 +8,5 @@ set_target_properties(scribe PROPERTIES FOLDER "Tools")
find_package(VHACD)
if(VHACD_FOUND)
add_subdirectory(vhacd)
set_target_properties(vhacd PROPERTIES FOLDER "Tools")
# set_target_properties(vhacd PROPERTIES FOLDER "Tools")
endif()

View file

@ -2,13 +2,13 @@
rm -f TAGS
find . -name *.h -print | while read I
find . -name *.h -print | grep -v build-ext |while read I
do
etags --append "$I"
done
find . -name *.cpp -print | grep -v 'moc_' | while read I
find . -name *.cpp -print | grep -v 'moc_' | grep -v build-ext | while read I
do
etags --append "$I"
done