mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 14:03:17 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into one
This commit is contained in:
commit
1192148a2a
45 changed files with 887 additions and 708 deletions
21
cmake/externals/etc2comp/CMakeLists.txt
vendored
21
cmake/externals/etc2comp/CMakeLists.txt
vendored
|
@ -33,23 +33,20 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
|||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
if (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/EtcLib.lib CACHE FILEPATH "Path to Etc2Comp debug library")
|
||||
if (WIN32 OR APPLE)
|
||||
if (WIN32)
|
||||
set(_LIB_FILE "EtcLib.lib")
|
||||
else ()
|
||||
set(_LIB_FILE "libEtcLib.a")
|
||||
endif ()
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/${_LIB_FILE} CACHE FILEPATH "Path to Etc2Comp debug library")
|
||||
|
||||
# use generator expression to ensure the correct library is found when building different configurations in VS
|
||||
set(_LIB_FOLDER "$<$<CONFIG:RelWithDebInfo>:build/EtcLib/RelWithDebInfo>")
|
||||
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<CONFIG:MinSizeRel>:build/EtcLib/MinSizeRel>")
|
||||
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<OR:$<CONFIG:Release>,$<CONFIG:Debug>>:build/EtcLib/Release>")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/EtcLib.lib CACHE FILEPATH "Path to Etc2Comp release library")
|
||||
|
||||
elseif (APPLE)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/libEtcLib.a CACHE FILEPATH "Path to EtcLib debug library")
|
||||
|
||||
set(_LIB_FOLDER "$<$<CONFIG:RelWithDebInfo>:build/EtcLib/RelWithDebInfo>")
|
||||
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<CONFIG:MinSizeRel>:build/EtcLib/MinSizeRel>")
|
||||
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<OR:$<CONFIG:Release>,$<CONFIG:Debug>>:build/EtcLib/Release>")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/libEtcLib.a CACHE FILEPATH "Path to Etc2Comp release library")
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/${_LIB_FILE} CACHE FILEPATH "Path to Etc2Comp release library")
|
||||
else ()
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to EtcLib debug library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/build/EtcLib/libEtcLib.a CACHE FILEPATH "Path to EtcLib release library")
|
||||
|
|
|
@ -440,8 +440,8 @@ QVariantMap AvatarActionHold::getArguments() {
|
|||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&]{
|
||||
arguments["holderID"] = _holderID;
|
||||
arguments["relativePosition"] = glmToQMap(_relativePosition);
|
||||
arguments["relativeRotation"] = glmToQMap(_relativeRotation);
|
||||
arguments["relativePosition"] = vec3ToQMap(_relativePosition);
|
||||
arguments["relativeRotation"] = quatToQMap(_relativeRotation);
|
||||
arguments["timeScale"] = _linearTimeScale;
|
||||
arguments["hand"] = _hand;
|
||||
arguments["kinematic"] = _kinematic;
|
||||
|
|
|
@ -121,6 +121,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
_headData = new MyHead(this);
|
||||
|
||||
_skeletonModel = std::make_shared<MySkeletonModel>(this, nullptr);
|
||||
_skeletonModel->setLoadingPriority(MYAVATAR_LOADING_PRIORITY);
|
||||
connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished);
|
||||
connect(_skeletonModel.get(), &Model::setURLFinished, this, [this](bool success) {
|
||||
if (success) {
|
||||
|
|
|
@ -41,12 +41,16 @@ bool Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offse
|
|||
glm::vec3 cameraPos = qApp->getCamera().getPosition();
|
||||
// use the referencial from the avatar, y isn't always up
|
||||
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation()*Vectors::UP;
|
||||
|
||||
glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP))));
|
||||
|
||||
transform.setRotation(rotation);
|
||||
transform.postRotate(offsetRotation);
|
||||
return true;
|
||||
// check to see if glm::lookAt will work / using glm::lookAt variable name
|
||||
glm::highp_vec3 s(glm::cross(billboardPos - cameraPos, avatarUP));
|
||||
|
||||
// make sure s is not NaN for any component
|
||||
if(glm::length2(s) > 0.0f) {
|
||||
glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP))));
|
||||
transform.setRotation(rotation);
|
||||
transform.postRotate(offsetRotation);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ const float DISPLAYNAME_FADE_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADE_TIME);
|
|||
const float DISPLAYNAME_ALPHA = 1.0f;
|
||||
const float DISPLAYNAME_BACKGROUND_ALPHA = 0.4f;
|
||||
const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f);
|
||||
const float Avatar::MYAVATAR_LOADING_PRIORITY = (float)M_PI; // Entity priority is computed as atan2(maxDim, distance) which is <= PI / 2
|
||||
const float Avatar::OTHERAVATAR_LOADING_PRIORITY = MYAVATAR_LOADING_PRIORITY - EPSILON;
|
||||
const float Avatar::ATTACHMENT_LOADING_PRIORITY = OTHERAVATAR_LOADING_PRIORITY - EPSILON;
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) {
|
||||
|
@ -551,10 +554,17 @@ void Avatar::measureMotionDerivatives(float deltaTime) {
|
|||
|
||||
// angular
|
||||
glm::quat orientation = getWorldOrientation();
|
||||
glm::quat delta = glm::inverse(_lastOrientation) * orientation;
|
||||
glm::vec3 angularVelocity = glm::axis(delta) * glm::angle(delta) * invDeltaTime;
|
||||
setWorldAngularVelocity(angularVelocity);
|
||||
_lastOrientation = getWorldOrientation();
|
||||
float changeDot = glm::abs(glm::dot(orientation, _lastOrientation));
|
||||
float CHANGE_DOT_THRESHOLD = 0.9999f;
|
||||
if (changeDot < CHANGE_DOT_THRESHOLD) {
|
||||
float angle = 2.0f * acosf(changeDot);
|
||||
glm::quat delta = glm::inverse(_lastOrientation) * orientation;
|
||||
glm::vec3 angularVelocity = (angle * invDeltaTime) * glm::axis(delta);
|
||||
setWorldAngularVelocity(angularVelocity);
|
||||
_lastOrientation = orientation;
|
||||
} else {
|
||||
setWorldAngularVelocity(glm::vec3(0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
enum TextRendererType {
|
||||
|
@ -1418,6 +1428,7 @@ void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
|||
if (_attachmentModels[i]->getURL() != attachmentData[i].modelURL) {
|
||||
_attachmentModelsTexturesLoaded[i] = false;
|
||||
}
|
||||
_attachmentModels[i]->setLoadingPriority(ATTACHMENT_LOADING_PRIORITY);
|
||||
_attachmentModels[i]->setURL(attachmentData[i].modelURL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -540,6 +540,10 @@ protected:
|
|||
AABox _renderBound;
|
||||
bool _isMeshVisible{ true };
|
||||
bool _needMeshVisibleSwitch{ true };
|
||||
|
||||
static const float MYAVATAR_LOADING_PRIORITY;
|
||||
static const float OTHERAVATAR_LOADING_PRIORITY;
|
||||
static const float ATTACHMENT_LOADING_PRIORITY;
|
||||
};
|
||||
|
||||
#endif // hifi_Avatar_h
|
||||
|
|
|
@ -12,6 +12,7 @@ OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) {
|
|||
// give the pointer to our head to inherited _headData variable from AvatarData
|
||||
_headData = new Head(this);
|
||||
_skeletonModel = std::make_shared<SkeletonModel>(this, nullptr);
|
||||
_skeletonModel->setLoadingPriority(OTHERAVATAR_LOADING_PRIORITY);
|
||||
connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished);
|
||||
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
|
||||
connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset);
|
||||
|
|
|
@ -2400,8 +2400,8 @@ QVariant AttachmentData::toVariant() const {
|
|||
QVariantMap result;
|
||||
result["modelUrl"] = modelURL;
|
||||
result["jointName"] = jointName;
|
||||
result["translation"] = glmToQMap(translation);
|
||||
result["rotation"] = glmToQMap(glm::degrees(safeEulerAngles(rotation)));
|
||||
result["translation"] = vec3ToQMap(translation);
|
||||
result["rotation"] = vec3ToQMap(glm::degrees(safeEulerAngles(rotation)));
|
||||
result["scale"] = scale;
|
||||
result["soft"] = isSoft;
|
||||
return result;
|
||||
|
|
|
@ -404,7 +404,6 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
uint64_t expiry = updateStart + timeBudget;
|
||||
|
||||
// process the sorted renderables
|
||||
std::unordered_map<EntityItemID, EntityRendererPointer>::iterator itr;
|
||||
size_t numSorted = sortedRenderables.size();
|
||||
while (!sortedRenderables.empty() && usecTimestampNow() < expiry) {
|
||||
const auto renderable = sortedRenderables.top().getRenderer();
|
||||
|
|
|
@ -284,8 +284,8 @@ bool EntityRenderer::addToScene(const ScenePointer& scene, Transaction& transact
|
|||
makeStatusGetters(_entity, statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
transaction.resetItem(_renderItemID, renderPayload);
|
||||
updateInScene(scene, transaction);
|
||||
onAddToScene(_entity);
|
||||
updateInScene(scene, transaction);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
}
|
||||
}
|
||||
|
||||
return model->needsReload();
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::updateModelBounds() {
|
||||
|
@ -1176,19 +1176,8 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
|||
}
|
||||
|
||||
bool ModelEntityRenderer::needsRenderUpdate() const {
|
||||
ModelPointer model;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
});
|
||||
|
||||
if (model) {
|
||||
if (_needsJointSimulation || _moving || _animating) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
// we will watch for that and ask the model to update it's render items
|
||||
if (_parsedModelURL != model->getURL()) {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (_moving || _animating) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1196,16 +1185,37 @@ bool ModelEntityRenderer::needsRenderUpdate() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!_prevModelLoaded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ModelPointer model;
|
||||
QUrl parsedModelURL;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
parsedModelURL = _parsedModelURL;
|
||||
});
|
||||
|
||||
if (model) {
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
// we will watch for that and ask the model to update it's render items
|
||||
if (parsedModelURL != model->getURL()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (model->needsReload()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME what is the difference between these two?
|
||||
if (model->needsFixupInScene()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME what is the difference between these two? ^^^^
|
||||
if (model->getRenderItemsNeedUpdate()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1219,7 +1229,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_lastModelURL != entity->getModelURL()) {
|
||||
if (_parsedModelURL != entity->getModelURL()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1232,10 +1242,6 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_renderAnimationProperties != entity->getAnimationProperties()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_animating != entity->isAnimatingSomething()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1249,7 +1255,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
});
|
||||
|
||||
if (model && model->isLoaded()) {
|
||||
if (!entity->_dimensionsInitialized || entity->_needsInitialSimulation) {
|
||||
if (!entity->_dimensionsInitialized || entity->_needsInitialSimulation || !entity->_originalTexturesRead) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1281,16 +1287,15 @@ void ModelEntityRenderer::setCollisionMeshKey(const void*key) {
|
|||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (_hasModel != entity->hasModel()) {
|
||||
_hasModel = entity->hasModel();
|
||||
withWriteLock([&] {
|
||||
_hasModel = entity->hasModel();
|
||||
});
|
||||
}
|
||||
|
||||
_marketplaceEntity = entity->getMarketplaceID().length() != 0;
|
||||
_animating = entity->isAnimatingSomething();
|
||||
|
||||
withWriteLock([&] {
|
||||
if (_lastModelURL != entity->getModelURL()) {
|
||||
_lastModelURL = entity->getModelURL();
|
||||
_parsedModelURL = QUrl(_lastModelURL);
|
||||
_animating = entity->isAnimatingSomething();
|
||||
if (_parsedModelURL != entity->getModelURL()) {
|
||||
_parsedModelURL = QUrl(entity->getModelURL());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1298,7 +1303,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
ModelPointer model;
|
||||
withReadLock([&] { model = _model; });
|
||||
if (!_hasModel) {
|
||||
if ((bool)model) {
|
||||
if (model) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
withWriteLock([&] { _model.reset(); });
|
||||
transaction.updateItem<PayloadProxyInterface>(getRenderItemID(), [](PayloadProxyInterface& data) {
|
||||
|
@ -1312,8 +1317,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
|
||||
// Check for addition
|
||||
if (_hasModel && !(bool)_model) {
|
||||
if (_hasModel && !model) {
|
||||
model = std::make_shared<Model>(nullptr, entity.get());
|
||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) {
|
||||
setKey(didVisualGeometryRequestSucceed);
|
||||
emit requestRenderUpdate();
|
||||
|
@ -1323,26 +1329,34 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
_didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed;
|
||||
});
|
||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
||||
entity->setModel(model);
|
||||
withWriteLock([&] { _model = model; });
|
||||
}
|
||||
|
||||
// From here on, we are guaranteed a populated model
|
||||
withWriteLock([&] {
|
||||
if (_parsedModelURL != model->getURL()) {
|
||||
if (_parsedModelURL != model->getURL()) {
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = false;
|
||||
model->setURL(_parsedModelURL);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Nothing else to do unless the model is loaded
|
||||
if (!model->isLoaded()) {
|
||||
withWriteLock([&] {
|
||||
_prevModelLoaded = false;
|
||||
});
|
||||
emit requestRenderUpdate();
|
||||
return;
|
||||
} else if (!_prevModelLoaded) {
|
||||
withWriteLock([&] {
|
||||
_prevModelLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Check for initializing the model
|
||||
// FIXME: There are several places below here where we are modifying the entity, which we should not be doing from the renderable
|
||||
if (!entity->_dimensionsInitialized) {
|
||||
EntityItemProperties properties;
|
||||
properties.setLastEdited(usecTimestampNow()); // we must set the edit time since we're editing it
|
||||
|
@ -1360,16 +1374,16 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
// Default to _originalTextures to avoid remapping immediately and lagging on load
|
||||
entity->_originalTextures = model->getTextures();
|
||||
entity->_originalTexturesRead = true;
|
||||
_currentTextures = entity->_originalTextures;
|
||||
}
|
||||
|
||||
if (_lastTextures != entity->getTextures()) {
|
||||
_texturesLoaded = false;
|
||||
_lastTextures = entity->getTextures();
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = false;
|
||||
_lastTextures = entity->getTextures();
|
||||
});
|
||||
auto newTextures = parseTexturesToMap(_lastTextures, entity->_originalTextures);
|
||||
if (newTextures != _currentTextures) {
|
||||
if (newTextures != model->getTextures()) {
|
||||
model->setTextures(newTextures);
|
||||
_currentTextures = newTextures;
|
||||
}
|
||||
}
|
||||
if (entity->_needsJointSimulation) {
|
||||
|
@ -1378,14 +1392,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
entity->updateModelBounds();
|
||||
entity->stopModelOverrideIfNoParent();
|
||||
|
||||
render::hifi::Tag tagMask = getTagMask();
|
||||
if (model->isVisible() != _visible) {
|
||||
// FIXME: this seems like it could be optimized if we tracked our last known visible state in
|
||||
// the renderable item. As it stands now the model checks it's visible/invisible state
|
||||
// so most of the time we don't do anything in this function.
|
||||
model->setVisibleInScene(_visible, scene);
|
||||
}
|
||||
|
||||
render::hifi::Tag tagMask = getTagMask();
|
||||
if (model->getTagMask() != tagMask) {
|
||||
model->setTagMask(tagMask, scene);
|
||||
}
|
||||
|
@ -1414,7 +1425,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
|
||||
if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) {
|
||||
_texturesLoaded = true;
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = true;
|
||||
});
|
||||
model->updateRenderItems();
|
||||
} else if (!_texturesLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
|
@ -1462,15 +1475,15 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
|||
batch.setModelTransform(getModelTransform()); // we want to include the scale as well
|
||||
DependencyManager::get<GeometryCache>()->renderWireCubeInstance(args, batch, greenColor);
|
||||
|
||||
// Enqueue updates for the next frame
|
||||
#if WANT_EXTRA_DEBUGGING
|
||||
// debugging...
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
_model->renderDebugMeshBoxes(batch);
|
||||
ModelPointer model;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
});
|
||||
if (model) {
|
||||
model->renderDebugMeshBoxes(batch);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Remap textures for the next frame to avoid flicker
|
||||
// remapTextures();
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames) {
|
||||
|
|
|
@ -170,7 +170,7 @@ protected:
|
|||
private:
|
||||
void animate(const TypedEntityPointer& entity);
|
||||
void mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames);
|
||||
bool jointsMapped() const { return _jointMappingURL == _renderAnimationProperties.getURL() && _jointMappingCompleted; }
|
||||
bool jointsMapped() const { return _jointMappingCompleted; }
|
||||
|
||||
// Transparency is handled in ModelMeshPartPayload
|
||||
virtual bool isTransparent() const override { return false; }
|
||||
|
@ -179,32 +179,26 @@ private:
|
|||
ModelPointer _model;
|
||||
GeometryResource::Pointer _compoundShapeResource;
|
||||
QString _lastTextures;
|
||||
QVariantMap _currentTextures;
|
||||
bool _texturesLoaded { false };
|
||||
AnimationPropertyGroup _renderAnimationProperties;
|
||||
int _lastKnownCurrentFrame { -1 };
|
||||
#ifdef MODEL_ENTITY_USE_FADE_EFFECT
|
||||
bool _hasTransitioned{ false };
|
||||
#endif
|
||||
|
||||
bool _needsJointSimulation { false };
|
||||
const void* _collisionMeshKey { nullptr };
|
||||
|
||||
// used on client side
|
||||
bool _jointMappingCompleted{ false };
|
||||
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
||||
QString _jointMappingURL;
|
||||
AnimationPointer _animation;
|
||||
QString _lastModelURL;
|
||||
QUrl _parsedModelURL;
|
||||
bool _marketplaceEntity { false };
|
||||
bool _shouldHighlight { false };
|
||||
bool _animating { false };
|
||||
uint64_t _lastAnimated { 0 };
|
||||
|
||||
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
|
||||
|
||||
bool _didLastVisualGeometryRequestSucceed { true };
|
||||
bool _prevModelLoaded { false };
|
||||
|
||||
void processMaterials();
|
||||
};
|
||||
|
|
|
@ -95,9 +95,6 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
|||
auto newParticleProperties = entity->getParticleProperties();
|
||||
if (!newParticleProperties.valid()) {
|
||||
qCWarning(entitiesrenderer) << "Bad particle properties";
|
||||
if (!entity->getParticleProperties().valid()) {
|
||||
qCWarning(entitiesrenderer) << "Bad particle properties";
|
||||
}
|
||||
}
|
||||
|
||||
if (resultWithReadLock<bool>([&]{ return _particleProperties != newParticleProperties; })) {
|
||||
|
@ -189,7 +186,7 @@ ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createPa
|
|||
if (polarStart == 0.0f && polarFinish == 0.0f && emitDimensions.z == 0.0f) {
|
||||
// Emit along z-axis from position
|
||||
|
||||
particle.velocity = (emitSpeed + 0.2f * speedSpread) * (emitOrientation * Vectors::UNIT_Z);
|
||||
particle.velocity = (emitSpeed + randFloatInRange(-1.0f, 1.0f) * speedSpread) * (emitOrientation * Vectors::UNIT_Z);
|
||||
particle.acceleration = emitAcceleration + randFloatInRange(-1.0f, 1.0f) * accelerationSpread;
|
||||
|
||||
} else {
|
||||
|
@ -198,10 +195,9 @@ ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createPa
|
|||
// - Distribute points relatively evenly over ellipsoid surface
|
||||
// - Distribute points relatively evenly within ellipsoid volume
|
||||
|
||||
float elevationMinZ = sin(PI_OVER_TWO - polarFinish);
|
||||
float elevationMaxZ = sin(PI_OVER_TWO - polarStart);
|
||||
// float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat());
|
||||
float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) *randFloat());
|
||||
float elevationMinZ = sinf(PI_OVER_TWO - polarFinish);
|
||||
float elevationMaxZ = sinf(PI_OVER_TWO - polarStart);
|
||||
float elevation = asinf(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat());
|
||||
|
||||
float azimuth;
|
||||
if (azimuthFinish >= azimuthStart) {
|
||||
|
@ -309,7 +305,6 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// FIXME migrate simulation to a compute stage
|
||||
stepSimulation();
|
||||
|
||||
|
|
|
@ -45,9 +45,8 @@ private:
|
|||
|
||||
// CPU particles
|
||||
// FIXME either switch to GPU compute particles or switch to simd updating of the particles
|
||||
#if 1
|
||||
struct CpuParticle {
|
||||
float seed{ 0.0f };
|
||||
float seed { 0.0f };
|
||||
uint64_t expiration { 0 };
|
||||
float lifetime { 0.0f };
|
||||
glm::vec3 position;
|
||||
|
@ -62,19 +61,6 @@ private:
|
|||
}
|
||||
};
|
||||
using CpuParticles = std::deque<CpuParticle>;
|
||||
#else
|
||||
struct CpuParticles {
|
||||
std::vector<float> seeds;
|
||||
std::vector<float> lifetimes;
|
||||
std::vector<vec4> positions;
|
||||
std::vector<vec4> velocities;
|
||||
std::vector<vec4> accelerations;
|
||||
|
||||
size_t size() const;
|
||||
void resize(size_t size);
|
||||
void integrate(float deltaTime);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include gpu/Noise.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
|
@ -119,9 +120,15 @@ void main(void) {
|
|||
// Offset for corrected vertex ordering.
|
||||
varTexcoord = vec2((UNIT_QUAD[twoTriID].xy -1.0) * vec2(0.5, -0.5));
|
||||
varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age);
|
||||
vec3 colorSpread = 2.0 * vec3(hifi_hash(seed), hifi_hash(seed * 2.0), hifi_hash(seed * 3.0)) - 1.0;
|
||||
varColor.rgb = clamp(varColor.rgb + colorSpread * particle.color.spread.rgb, vec3(0), vec3(1));
|
||||
float alphaSpread = 2.0 * hifi_hash(seed * 4.0) - 1.0;
|
||||
varColor.a = clamp(varColor.a + alphaSpread * particle.color.spread.a, 0.0, 1.0);
|
||||
|
||||
// anchor point in eye space
|
||||
float radius = interpolate3Points(particle.radius.start, particle.radius.middle, particle.radius.finish, age);
|
||||
float radiusSpread = 2.0 * hifi_hash(seed * 5.0) - 1.0;
|
||||
radius = max(radius + radiusSpread * particle.radius.spread, 0.0);
|
||||
vec4 quadPos = radius * UNIT_QUAD[twoTriID];
|
||||
|
||||
vec4 anchorPoint;
|
||||
|
|
|
@ -854,7 +854,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* default is Earth's gravity value.
|
||||
* @property {vec3} accelerationSpread=0,0,0 - The spread in accelerations that each particle is given. If
|
||||
* <code>emitAccelerations == {x: 0, y: -9.8, z: 0}</code> and <code>accelerationSpread ==
|
||||
* {x: 0, y: 1, z: 0}</code>, each particle will have an acceleration in the range, <code>{x: 0, y: -10.8, z: 0}</code>
|
||||
* {x: 0, y: 1, z: 0}</code>, each particle will have an acceleration in the range <code>{x: 0, y: -10.8, z: 0}</code>
|
||||
* – <code>{x: 0, y: -8.8, z: 0}</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the particle effect, i.e., a bounding box containing all the particles
|
||||
* during their lifetimes, assuming that <code>emitterShouldTrail</code> is <code>false</code>. <em>Read-only.</em>
|
||||
|
@ -879,30 +879,35 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* @property {number} azimuthStart=-Math.PI - The angle in radians from the entity's local x-axis about the entity's local
|
||||
* z-axis at which particles start being emitted; range <code>-Math.PI</code> – <code>Math.PI</code>. Particles are
|
||||
* emitted from the portion of the ellipsoid that lies between <code>azimuthStart<code> and <code>azimuthFinish</code>.
|
||||
* @property {number} azimuthFinish=Math.PI - The angle in radians from the entity's local x-axis about the entity's local
|
||||
* z-axis at which particles stop being emitted; range <code>-Math.PI</code> – <code>Math.PI</code>. Particles are
|
||||
* @property {number} azimuthFinish=Math.PI - The angle in radians from the entity's local x-axis about the entity's local
|
||||
* z-axis at which particles stop being emitted; range <code>-Math.PI</code> – <code>Math.PI</code>. Particles are
|
||||
* emitted from the portion of the ellipsoid that lies between <code>azimuthStart<code> and <code>azimuthFinish</code>.
|
||||
*
|
||||
* @property {string} textures="" - The URL of a JPG or PNG image file to display for each particle. If you want transparency,
|
||||
* @property {string} textures="" - The URL of a JPG or PNG image file to display for each particle. If you want transparency,
|
||||
* use PNG format.
|
||||
* @property {number} particleRadius=0.025 - The radius of each particle at the middle of its life.
|
||||
* @property {number} radiusStart=0.025 - The radius of each particle at the start of its life. If not explicitly set, the
|
||||
* @property {number} radiusStart=NAN - The radius of each particle at the start of its life. If NAN, the
|
||||
* <code>particleRadius</code> value is used.
|
||||
* @property {number} radiusFinish=0.025 - The radius of each particle at the end of its life. If not explicitly set, the
|
||||
* @property {number} radiusFinish=NAN - The radius of each particle at the end of its life. If NAN, the
|
||||
* <code>particleRadius</code> value is used.
|
||||
* @property {number} radiusSpread=0 - <em>Currently not used.</em>
|
||||
* @property {number} radiusSpread=0 - The spread in radius that each particle is given. If <code>particleRadius == 0.5</code>
|
||||
* and <code>radiusSpread == 0.25</code>, each particle will have a radius in the range <code>0.25</code> – <code>0.75</code>.
|
||||
* @property {Color} color=255,255,255 - The color of each particle at the middle of its life.
|
||||
* @property {Color} colorStart=255,255,255 - The color of each particle at the start of its life. If not explicitly set, the
|
||||
* @property {Color} colorStart=NAN,NAN,NAN - The color of each particle at the start of its life. If any of the values are NAN, the
|
||||
* <code>color</code> value is used.
|
||||
* @property {Color} colorFinish=255,255,255 - The color of each particle at the end of its life. If not explicitly set, the
|
||||
* @property {Color} colorFinish=NAN,NAN,NAN - The color of each particle at the end of its life. If any of the values are NAN, the
|
||||
* <code>color</code> value is used.
|
||||
* @property {Color} colorSpread=0,0,0 - <em>Currently not used.</em>
|
||||
* @property {Color} colorSpread=0,0,0 - The spread in color that each particle is given. If
|
||||
* <code>color == {red: 100, green: 100, blue: 100}</code> and <code>colorSpread ==
|
||||
* {red: 10, green: 25, blue: 50}</code>, each particle will have an acceleration in the range <code>{red: 90, green: 75, blue: 50}</code>
|
||||
* – <code>{red: 110, green: 125, blue: 150}</code>.
|
||||
* @property {number} alpha=1 - The alpha of each particle at the middle of its life.
|
||||
* @property {number} alphaStart=1 - The alpha of each particle at the start of its life. If not explicitly set, the
|
||||
* @property {number} alphaStart=NAN - The alpha of each particle at the start of its life. If NAN, the
|
||||
* <code>alpha</code> value is used.
|
||||
* @property {number} alphaFinish=1 - The alpha of each particle at the end of its life. If not explicitly set, the
|
||||
* @property {number} alphaFinish=NAN - The alpha of each particle at the end of its life. If NAN, the
|
||||
* <code>alpha</code> value is used.
|
||||
* @property {number} alphaSpread=0 - <em>Currently not used.</em>
|
||||
* @property {number} alphaSpread=0 - The spread in alpha that each particle is given. If <code>alpha == 0.5</code>
|
||||
* and <code>alphaSpread == 0.25</code>, each particle will have an alpha in the range <code>0.25</code> – <code>0.75</code>.
|
||||
*
|
||||
* @property {ShapeType} shapeType="none" - <em>Currently not used.</em> <em>Read-only.</em>
|
||||
*
|
||||
|
@ -1499,13 +1504,13 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
}
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lastEditedBy, QUuid, setLastEditedBy);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(position, glmVec3, setPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, glmVec3, setDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, glmQuat, setRotation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(position, vec3, setPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, vec3, setDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, quat, setRotation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(density, float, setDensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(velocity, glmVec3, setVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(gravity, glmVec3, setGravity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(acceleration, glmVec3, setAcceleration);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(velocity, vec3, setVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(gravity, vec3, setGravity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(acceleration, vec3, setAcceleration);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(damping, float, setDamping);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(restitution, float, setRestitution);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(friction, float, setFriction);
|
||||
|
@ -1513,15 +1518,15 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(script, QString, setScript);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(scriptTimestamp, quint64, setScriptTimestamp);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(serverScripts, QString, setServerScripts);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, glmVec3, setRegistrationPoint);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, vec3, setRegistrationPoint);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, vec3, setAngularVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(visible, bool, setVisible);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(canCastShadow, bool, setCanCastShadow);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(color, xColor, setColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorSpread, xColor, setColorSpread);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorStart, xColor, setColorStart);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorFinish, xColor, setColorFinish);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorStart, vec3, setColorStart);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorFinish, vec3, setColorFinish);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(alpha, float, setAlpha);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaSpread, float, setAlphaSpread);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaStart, float, setAlphaStart);
|
||||
|
@ -1555,15 +1560,15 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitSpeed, float, setEmitSpeed);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(speedSpread, float, setSpeedSpread);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitOrientation, glmQuat, setEmitOrientation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitDimensions, glmVec3, setEmitDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitOrientation, quat, setEmitOrientation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitDimensions, vec3, setEmitDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRadiusStart, float, setEmitRadiusStart);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(polarStart, float, setPolarStart);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(polarFinish, float, setPolarFinish);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(azimuthStart, float, setAzimuthStart);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(azimuthFinish, float, setAzimuthFinish);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitAcceleration, glmVec3, setEmitAcceleration);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(accelerationSpread, glmVec3, setAccelerationSpread);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitAcceleration, vec3, setEmitAcceleration);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(accelerationSpread, vec3, setAccelerationSpread);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusSpread, float, setRadiusSpread);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusStart, float, setRadiusStart);
|
||||
|
@ -1573,8 +1578,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(materialMappingMode, MaterialMappingMode);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, quint16, setPriority);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentMaterialName, QString, setParentMaterialName);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingPos, glmVec2, setMaterialMappingPos);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, glmVec2, setMaterialMappingScale);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingPos, vec2, setMaterialMappingPos);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, vec2, setMaterialMappingScale);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera);
|
||||
|
@ -1601,7 +1606,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, glmVec3, setVoxelVolumeSize);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, vec3, setVoxelVolumeSize);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelData, QByteArray, setVoxelData);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelSurfaceStyle, uint16_t, setVoxelSurfaceStyle);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lineWidth, float, setLineWidth);
|
||||
|
@ -1648,11 +1653,11 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(parentJointIndex, quint16, setParentJointIndex);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(queryAACube, AACube, setQueryAACube);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localPosition, glmVec3, setLocalPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, glmQuat, setLocalRotation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localVelocity, glmVec3, setLocalVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localAngularVelocity, glmVec3, setLocalAngularVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localDimensions, glmVec3, setLocalDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localPosition, vec3, setLocalPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, quat, setLocalRotation);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localVelocity, vec3, setLocalVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localAngularVelocity, vec3, setLocalAngularVelocity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(localDimensions, vec3, setLocalDimensions);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotationsSet, qVectorBool, setJointRotationsSet);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotations, qVectorQuat, setJointRotations);
|
||||
|
@ -1896,8 +1901,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_START, ColorStart, colorStart, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_FINISH, ColorFinish, colorFinish, xColor);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_START, ColorStart, colorStart, vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COLOR_FINISH, ColorFinish, colorFinish, vec3);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA, Alpha, alpha, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float);
|
||||
|
@ -1952,8 +1957,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_MODE, MaterialMappingMode, materialMappingMode, MaterialMappingMode);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_PRIORITY, Priority, priority, quint16);
|
||||
ADD_PROPERTY_TO_MAP(PROP_PARENT_MATERIAL_NAME, ParentMaterialName, parentMaterialName, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glmVec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glmVec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, vec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, vec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_DATA, MaterialData, materialData, QString);
|
||||
|
||||
|
@ -2656,8 +2661,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RADIUS_START, float, setRadiusStart);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RADIUS_FINISH, float, setRadiusFinish);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_SPREAD, xColor, setColorSpread);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_START, xColor, setColorStart);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_FINISH, xColor, setColorFinish);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_START, vec3, setColorStart);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR_FINISH, vec3, setColorFinish);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_SPREAD, float, setAlphaSpread);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_START, float, setAlphaStart);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_FINISH, float, setAlphaFinish);
|
||||
|
@ -2729,8 +2734,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_MODE, MaterialMappingMode, setMaterialMappingMode);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_PRIORITY, quint16, setPriority);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_MATERIAL_NAME, QString, setParentMaterialName);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_POS, glmVec2, setMaterialMappingPos);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_SCALE, glmVec2, setMaterialMappingScale);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_POS, vec2, setMaterialMappingPos);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_SCALE, vec2, setMaterialMappingScale);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_DATA, QString, setMaterialData);
|
||||
}
|
||||
|
@ -2800,7 +2805,7 @@ QVector<glm::vec3> EntityItemProperties::unpackStrokeColors(const QByteArray& st
|
|||
float r = (uint8_t)strokeColors[i++] / 255.0f;
|
||||
float g = (uint8_t)strokeColors[i++] / 255.0f;
|
||||
float b = (uint8_t)strokeColors[i++] / 255.0f;
|
||||
unpackedStrokeColors[j++] = glmVec3(r, g, b);
|
||||
unpackedStrokeColors[j++] = vec3(r, g, b);
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "WARNING - Expected received size for stroke colors does not match. Expected: "
|
||||
|
@ -2931,6 +2936,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_shapeTypeChanged = true;
|
||||
|
||||
_isEmittingChanged = true;
|
||||
_emitterShouldTrail = true;
|
||||
_maxParticlesChanged = true;
|
||||
_lifespanChanged = true;
|
||||
_emitRateChanged = true;
|
||||
|
@ -2949,15 +2955,12 @@ void EntityItemProperties::markAllChanged() {
|
|||
_radiusSpreadChanged = true;
|
||||
_colorSpreadChanged = true;
|
||||
_alphaSpreadChanged = true;
|
||||
|
||||
// Only mark the following as changed if their values are specified in the properties when the particle is created. If their
|
||||
// values are specified then they are marked as changed in getChangedProperties().
|
||||
//_radiusStartChanged = true;
|
||||
//_radiusFinishChanged = true;
|
||||
//_colorStartChanged = true;
|
||||
//_colorFinishChanged = true;
|
||||
//_alphaStartChanged = true;
|
||||
//_alphaFinishChanged = true;
|
||||
_radiusStartChanged = true;
|
||||
_radiusFinishChanged = true;
|
||||
_colorStartChanged = true;
|
||||
_colorFinishChanged = true;
|
||||
_alphaStartChanged = true;
|
||||
_alphaFinishChanged = true;
|
||||
|
||||
_materialURLChanged = true;
|
||||
_materialMappingModeChanged = true;
|
||||
|
|
|
@ -134,14 +134,14 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT);
|
||||
DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP);
|
||||
DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor, particle::DEFAULT_COLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor, particle::DEFAULT_COLOR_SPREAD);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, xColor, particle::DEFAULT_COLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_FINISH, ColorFinish, colorFinish, xColor, particle::DEFAULT_COLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor, ParticleEffectEntityItem::DEFAULT_XCOLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor, ParticleEffectEntityItem::DEFAULT_XCOLOR_SPREAD);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, vec3, particle::DEFAULT_COLOR_UNINITIALIZED);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_FINISH, ColorFinish, colorFinish, vec3, particle::DEFAULT_COLOR_UNINITIALIZED);
|
||||
DEFINE_PROPERTY(PROP_ALPHA, Alpha, alpha, float, particle::DEFAULT_ALPHA);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float, particle::DEFAULT_ALPHA_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_START, AlphaStart, alphaStart, float, particle::DEFAULT_ALPHA);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float, particle::DEFAULT_ALPHA);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_START, AlphaStart, alphaStart, float, particle::DEFAULT_ALPHA_START);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float, particle::DEFAULT_ALPHA_FINISH);
|
||||
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT);
|
||||
|
@ -228,8 +228,8 @@ public:
|
|||
DEFINE_PROPERTY_REF_ENUM(PROP_MATERIAL_MAPPING_MODE, MaterialMappingMode, materialMappingMode, MaterialMappingMode, UV);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, quint16, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_MATERIAL_NAME, ParentMaterialName, parentMaterialName, QString, "0");
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glmVec2, glm::vec2(0, 0));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glmVec2, glm::vec2(1, 1));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, vec2, glm::vec2(0, 0));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, vec2, glm::vec2(1, 1));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, "");
|
||||
|
||||
|
@ -249,11 +249,11 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_STATIC_CERTIFICATE_VERSION, StaticCertificateVersion, staticCertificateVersion, quint32, ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION);
|
||||
|
||||
// these are used when bouncing location data into and out of scripts
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_POSITION, LocalPosition, localPosition, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glmQuat, ENTITY_ITEM_DEFAULT_ROTATION);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_DIMENSIONS, LocalDimensions, localDimensions, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_POSITION, LocalPosition, localPosition, vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_ROTATION, LocalRotation, localRotation, quat, ENTITY_ITEM_DEFAULT_ROTATION);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_DIMENSIONS, LocalDimensions, localDimensions, vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
|
||||
DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector<bool>, QVector<bool>());
|
||||
DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector<glm::quat>, QVector<glm::quat>());
|
||||
|
|
|
@ -185,9 +185,6 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu
|
|||
properties.setProperty(#P, V); \
|
||||
}
|
||||
|
||||
typedef glm::vec2 glmVec2;
|
||||
typedef glm::vec3 glmVec3;
|
||||
typedef glm::quat glmQuat;
|
||||
typedef QVector<glm::vec3> qVectorVec3;
|
||||
typedef QVector<glm::quat> qVectorQuat;
|
||||
typedef QVector<bool> qVectorBool;
|
||||
|
@ -224,7 +221,7 @@ inline QByteArray QByteArray_convertFromScriptValue(const QScriptValue& v, bool&
|
|||
return QByteArray::fromBase64(b64.toUtf8());
|
||||
}
|
||||
|
||||
inline glmVec2 glmVec2_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
inline glm::vec2 vec2_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
QScriptValue y = v.property("y");
|
||||
|
@ -241,11 +238,20 @@ inline glmVec2 glmVec2_convertFromScriptValue(const QScriptValue& v, bool& isVal
|
|||
return glm::vec2(0);
|
||||
}
|
||||
|
||||
inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
inline glm::vec3 vec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
QScriptValue y = v.property("y");
|
||||
QScriptValue z = v.property("z");
|
||||
if (!x.isValid()) {
|
||||
x = v.property("red");
|
||||
}
|
||||
if (!y.isValid()) {
|
||||
y = v.property("green");
|
||||
}
|
||||
if (!z.isValid()) {
|
||||
z = v.property("blue");
|
||||
}
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
glm::vec3 newValue(0);
|
||||
newValue.x = x.toVariant().toFloat();
|
||||
|
@ -288,7 +294,7 @@ inline qVectorBool qVectorBool_convertFromScriptValue(const QScriptValue& v, boo
|
|||
return qVectorBoolFromScriptValue(v);
|
||||
}
|
||||
|
||||
inline glmQuat glmQuat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
inline glm::quat quat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
isValid = false; /// assume it can't be converted
|
||||
QScriptValue x = v.property("x");
|
||||
QScriptValue y = v.property("y");
|
||||
|
@ -317,6 +323,15 @@ inline xColor xColor_convertFromScriptValue(const QScriptValue& v, bool& isValid
|
|||
QScriptValue r = v.property("red");
|
||||
QScriptValue g = v.property("green");
|
||||
QScriptValue b = v.property("blue");
|
||||
if (!r.isValid()) {
|
||||
r = v.property("x");
|
||||
}
|
||||
if (!g.isValid()) {
|
||||
g = v.property("y");
|
||||
}
|
||||
if (!b.isValid()) {
|
||||
b = v.property("z");
|
||||
}
|
||||
if (r.isValid() && g.isValid() && b.isValid()) {
|
||||
newValue.red = r.toVariant().toInt();
|
||||
newValue.green = g.toVariant().toInt();
|
||||
|
|
|
@ -739,15 +739,15 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesInFrustum(QVariantMap frust
|
|||
|
||||
const QString POSITION_PROPERTY = "position";
|
||||
bool positionOK = frustum.contains(POSITION_PROPERTY);
|
||||
glm::vec3 position = positionOK ? qMapToGlmVec3(frustum[POSITION_PROPERTY]) : glm::vec3();
|
||||
glm::vec3 position = positionOK ? qMapToVec3(frustum[POSITION_PROPERTY]) : glm::vec3();
|
||||
|
||||
const QString ORIENTATION_PROPERTY = "orientation";
|
||||
bool orientationOK = frustum.contains(ORIENTATION_PROPERTY);
|
||||
glm::quat orientation = orientationOK ? qMapToGlmQuat(frustum[ORIENTATION_PROPERTY]) : glm::quat();
|
||||
glm::quat orientation = orientationOK ? qMapToQuat(frustum[ORIENTATION_PROPERTY]) : glm::quat();
|
||||
|
||||
const QString PROJECTION_PROPERTY = "projection";
|
||||
bool projectionOK = frustum.contains(PROJECTION_PROPERTY);
|
||||
glm::mat4 projection = projectionOK ? qMapToGlmMat4(frustum[PROJECTION_PROPERTY]) : glm::mat4();
|
||||
glm::mat4 projection = projectionOK ? qMapToMat4(frustum[PROJECTION_PROPERTY]) : glm::mat4();
|
||||
|
||||
const QString CENTER_RADIUS_PROPERTY = "centerRadius";
|
||||
bool centerRadiusOK = frustum.contains(CENTER_RADIUS_PROPERTY);
|
||||
|
|
|
@ -35,13 +35,13 @@ void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desired
|
|||
void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, color, xColor, setColor);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, intensity, float, setIntensity);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, glmVec3, setDirection);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, vec3, setDirection);
|
||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, castShadows, bool, setCastShadows);
|
||||
|
||||
// legacy property support
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightColor, xColor, setColor, getColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightIntensity, float, setIntensity, getIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightDirection, glmVec3, setDirection, getDirection);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightDirection, vec3, setDirection, getDirection);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightCastShadows, bool, setCastShadows, getCastShadows);
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,8 @@ uint64_t Properties::emitIntervalUsecs() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const xColor ParticleEffectEntityItem::DEFAULT_XCOLOR = xColor(static_cast<unsigned char>(DEFAULT_COLOR.r), static_cast<unsigned char>(DEFAULT_COLOR.g), static_cast<unsigned char>(DEFAULT_COLOR.b));
|
||||
const xColor ParticleEffectEntityItem::DEFAULT_XCOLOR_SPREAD = xColor(static_cast<unsigned char>(DEFAULT_COLOR_SPREAD.r), static_cast<unsigned char>(DEFAULT_COLOR_SPREAD.g), static_cast<unsigned char>(DEFAULT_COLOR_SPREAD.b));
|
||||
|
||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity(new ParticleEffectEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
|
@ -152,18 +154,6 @@ EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID
|
|||
return entity;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void ParticleEffectEntityItem::checkValid() {
|
||||
bool result;
|
||||
withReadLock([&] {
|
||||
result = _particleProperties.valid();
|
||||
});
|
||||
if (!result) {
|
||||
qCWarning(entities) << "Invalid particle properties";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID) :
|
||||
EntityItem(entityItemID)
|
||||
|
@ -180,15 +170,13 @@ void ParticleEffectEntityItem::setAlpha(float alpha) {
|
|||
|
||||
void ParticleEffectEntityItem::setAlphaStart(float alphaStart) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.alpha.range.start = glm::clamp(alphaStart, MINIMUM_ALPHA, MAXIMUM_ALPHA);
|
||||
_isAlphaStartInitialized = true;
|
||||
_particleProperties.alpha.range.start = glm::isnan(alphaStart) ? alphaStart : glm::clamp(alphaStart, MINIMUM_ALPHA, MAXIMUM_ALPHA);
|
||||
});
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setAlphaFinish(float alphaFinish) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.alpha.range.finish = glm::clamp(alphaFinish, MINIMUM_ALPHA, MAXIMUM_ALPHA);
|
||||
_isAlphaFinishInitialized = true;
|
||||
_particleProperties.alpha.range.finish = glm::isnan(alphaFinish) ? alphaFinish : glm::clamp(alphaFinish, MINIMUM_ALPHA, MAXIMUM_ALPHA);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -199,9 +187,13 @@ void ParticleEffectEntityItem::setAlphaSpread(float alphaSpread) {
|
|||
}
|
||||
|
||||
void ParticleEffectEntityItem::setLifespan(float lifespan) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.lifespan = glm::clamp(lifespan, MINIMUM_LIFESPAN, MAXIMUM_LIFESPAN);
|
||||
});
|
||||
lifespan = glm::clamp(lifespan, MINIMUM_LIFESPAN, MAXIMUM_LIFESPAN);
|
||||
if (lifespan != _particleProperties.lifespan) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.lifespan = lifespan;
|
||||
});
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitRate(float emitRate) {
|
||||
|
@ -232,10 +224,12 @@ void ParticleEffectEntityItem::setSpeedSpread(float speedSpread) {
|
|||
|
||||
void ParticleEffectEntityItem::setEmitOrientation(const glm::quat& emitOrientation_) {
|
||||
auto emitOrientation = glm::normalize(emitOrientation_);
|
||||
withWriteLock([&] {
|
||||
_particleProperties.emission.orientation = emitOrientation;
|
||||
});
|
||||
computeAndUpdateDimensions();
|
||||
if (emitOrientation != _particleProperties.emission.orientation) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.emission.orientation = emitOrientation;
|
||||
});
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitDimensions(const glm::vec3& emitDimensions_) {
|
||||
|
@ -281,15 +275,9 @@ void ParticleEffectEntityItem::setAzimuthFinish(float azimuthFinish) {
|
|||
void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration_) {
|
||||
auto emitAcceleration = glm::clamp(emitAcceleration_, vec3(MINIMUM_EMIT_ACCELERATION), vec3(MAXIMUM_EMIT_ACCELERATION));
|
||||
if (emitAcceleration != _particleProperties.emission.acceleration.target) {
|
||||
if (!_particleProperties.valid()) {
|
||||
qCWarning(entities) << "Bad particle data";
|
||||
}
|
||||
withWriteLock([&] {
|
||||
_particleProperties.emission.acceleration.target = emitAcceleration;
|
||||
});
|
||||
if (!_particleProperties.valid()) {
|
||||
qCWarning(entities) << "Bad particle data";
|
||||
}
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
@ -305,29 +293,43 @@ void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerati
|
|||
}
|
||||
|
||||
void ParticleEffectEntityItem::setParticleRadius(float particleRadius) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.gradient.target = glm::clamp(particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
});
|
||||
particleRadius = glm::clamp(particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
if (particleRadius != _particleProperties.radius.gradient.target) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.gradient.target = particleRadius;
|
||||
});
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setRadiusStart(float radiusStart) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.range.start = glm::clamp(radiusStart, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
_isRadiusStartInitialized = true;
|
||||
});
|
||||
radiusStart = glm::isnan(radiusStart) ? radiusStart : glm::clamp(radiusStart, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
if (radiusStart != _particleProperties.radius.range.start) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.range.start = radiusStart;
|
||||
});
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setRadiusFinish(float radiusFinish) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.range.finish = glm::clamp(radiusFinish, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
_isRadiusFinishInitialized = true;
|
||||
});
|
||||
radiusFinish = glm::isnan(radiusFinish) ? radiusFinish : glm::clamp(radiusFinish, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
if (radiusFinish != _particleProperties.radius.range.finish) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.range.finish = radiusFinish;
|
||||
});
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.gradient.spread = glm::clamp(radiusSpread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
});
|
||||
void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) {
|
||||
radiusSpread = glm::clamp(radiusSpread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
if (radiusSpread != _particleProperties.radius.gradient.spread) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.radius.gradient.spread = radiusSpread;
|
||||
});
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -342,8 +344,15 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() {
|
|||
glm::vec3 velocity = particleProperties.emission.speed.target * direction;
|
||||
glm::vec3 velocitySpread = particleProperties.emission.speed.spread * direction;
|
||||
glm::vec3 maxVelocity = glm::abs(velocity) + velocitySpread;
|
||||
glm::vec3 maxAccleration = glm::abs(_acceleration) + particleProperties.emission.acceleration.spread;
|
||||
glm::vec3 maxDistance = 0.5f * particleProperties.emission.dimensions + time * maxVelocity + (0.5f * time * time) * maxAccleration;
|
||||
glm::vec3 maxAccleration = glm::abs(particleProperties.emission.acceleration.target) + particleProperties.emission.acceleration.spread;
|
||||
float maxRadius = particleProperties.radius.gradient.target;
|
||||
if (!glm::isnan(particleProperties.radius.range.start)) {
|
||||
maxRadius = glm::max(maxRadius, particleProperties.radius.range.start);
|
||||
}
|
||||
if (!glm::isnan(particleProperties.radius.range.finish)) {
|
||||
maxRadius = glm::max(maxRadius, particleProperties.radius.range.finish);
|
||||
}
|
||||
glm::vec3 maxDistance = 0.5f * particleProperties.emission.dimensions + time * maxVelocity + (0.5f * time * time) * maxAccleration + vec3(maxRadius + particleProperties.radius.gradient.spread);
|
||||
if (isNaN(maxDistance)) {
|
||||
qCWarning(entities) << "Bad particle data";
|
||||
return;
|
||||
|
@ -390,7 +399,6 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitterShouldTrail, getEmitterShouldTrail);
|
||||
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -441,18 +449,26 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
|
|||
return somethingChanged;
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setColor(const rgbColor& value) {
|
||||
memcpy(_particleColorHack, value, sizeof(rgbColor));
|
||||
_particleProperties.color.gradient.target.red = value[RED_INDEX];
|
||||
_particleProperties.color.gradient.target.green = value[GREEN_INDEX];
|
||||
_particleProperties.color.gradient.target.blue = value[BLUE_INDEX];
|
||||
void ParticleEffectEntityItem::setColor(const vec3& value) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.color.gradient.target = value;
|
||||
});
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setColor(const xColor& value) {
|
||||
_particleProperties.color.gradient.target = value;
|
||||
_particleColorHack[RED_INDEX] = value.red;
|
||||
_particleColorHack[GREEN_INDEX] = value.green;
|
||||
_particleColorHack[BLUE_INDEX] = value.blue;
|
||||
withWriteLock([&] {
|
||||
_particleProperties.color.gradient.target.r = value.red;
|
||||
_particleProperties.color.gradient.target.g = value.green;
|
||||
_particleProperties.color.gradient.target.b = value.blue;
|
||||
});
|
||||
}
|
||||
|
||||
xColor ParticleEffectEntityItem::getXColor() const {
|
||||
xColor color;
|
||||
color.red = _particleProperties.color.gradient.target.r;
|
||||
color.green = _particleProperties.color.gradient.target.g;
|
||||
color.blue = _particleProperties.color.gradient.target.b;
|
||||
return color;
|
||||
}
|
||||
|
||||
int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
|
@ -463,15 +479,15 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, xColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, vec3, setEmitAcceleration);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, vec3, setAccelerationSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
|
@ -480,8 +496,8 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
READ_ENTITY_PROPERTY(PROP_RADIUS_FINISH, float, setRadiusFinish);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_SPREAD, xColor, setColorSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_START, xColor, setColorStart);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_FINISH, xColor, setColorFinish);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_START, vec3, setColorStart);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_FINISH, vec3, setColorFinish);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, float, setAlphaSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_START, float, setAlphaStart);
|
||||
|
@ -489,8 +505,8 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_SPEED, float, setEmitSpeed);
|
||||
READ_ENTITY_PROPERTY(PROP_SPEED_SPREAD, float, setSpeedSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, glm::quat, setEmitOrientation);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, glm::vec3, setEmitDimensions);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, quat, setEmitOrientation);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, vec3, setEmitDimensions);
|
||||
READ_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, float, setEmitRadiusStart);
|
||||
READ_ENTITY_PROPERTY(PROP_POLAR_START, float, setPolarStart);
|
||||
READ_ENTITY_PROPERTY(PROP_POLAR_FINISH, float, setPolarFinish);
|
||||
|
@ -548,7 +564,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
|
|||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getXColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, getIsEmitting());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles());
|
||||
|
@ -585,10 +601,10 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
|
|||
void ParticleEffectEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(entities) << "PA EFFECT EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " color:" <<
|
||||
_particleProperties.color.gradient.target.red << "," <<
|
||||
_particleProperties.color.gradient.target.green << "," <<
|
||||
_particleProperties.color.gradient.target.blue;
|
||||
qCDebug(entities) << " color:" <<
|
||||
_particleProperties.color.gradient.target.r << "," <<
|
||||
_particleProperties.color.gradient.target.g << "," <<
|
||||
_particleProperties.color.gradient.target.b;
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions());
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
|
@ -604,15 +620,9 @@ void ParticleEffectEntityItem::setShapeType(ShapeType type) {
|
|||
}
|
||||
|
||||
void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) {
|
||||
_particleProperties.maxParticles = glm::clamp(maxParticles, MINIMUM_MAX_PARTICLES, MAXIMUM_MAX_PARTICLES);
|
||||
}
|
||||
|
||||
QString ParticleEffectEntityItem::getTextures() const {
|
||||
QString result;
|
||||
withReadLock([&] {
|
||||
result = _particleProperties.textures;
|
||||
withWriteLock([&] {
|
||||
_particleProperties.maxParticles = glm::clamp(maxParticles, MINIMUM_MAX_PARTICLES, MAXIMUM_MAX_PARTICLES);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setTextures(const QString& textures) {
|
||||
|
@ -621,25 +631,69 @@ void ParticleEffectEntityItem::setTextures(const QString& textures) {
|
|||
});
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setColorStart(const vec3& colorStart) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.color.range.start = colorStart;
|
||||
});
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setColorFinish(const vec3& colorFinish) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.color.range.finish = colorFinish;
|
||||
});
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setColorSpread(const xColor& value) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.color.gradient.spread.r = value.red;
|
||||
_particleProperties.color.gradient.spread.g = value.green;
|
||||
_particleProperties.color.gradient.spread.b = value.blue;
|
||||
});
|
||||
}
|
||||
|
||||
xColor ParticleEffectEntityItem::getColorSpread() const {
|
||||
xColor color;
|
||||
color.red = _particleProperties.color.gradient.spread.r;
|
||||
color.green = _particleProperties.color.gradient.spread.g;
|
||||
color.blue = _particleProperties.color.gradient.spread.b;
|
||||
return color;
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitterShouldTrail(bool emitterShouldTrail) {
|
||||
withWriteLock([&] {
|
||||
_particleProperties.emission.shouldTrail = emitterShouldTrail;
|
||||
});
|
||||
}
|
||||
|
||||
particle::Properties ParticleEffectEntityItem::getParticleProperties() const {
|
||||
particle::Properties result;
|
||||
withReadLock([&] {
|
||||
result = _particleProperties;
|
||||
});
|
||||
withReadLock([&] {
|
||||
result = _particleProperties;
|
||||
|
||||
// Special case the properties that get treated differently if they're unintialized
|
||||
result.color.range.start = getColorStart();
|
||||
result.color.range.finish = getColorFinish();
|
||||
result.alpha.range.start = getAlphaStart();
|
||||
result.alpha.range.finish = getAlphaFinish();
|
||||
result.radius.range.start = getRadiusStart();
|
||||
result.radius.range.finish = getRadiusFinish();
|
||||
// Special case the properties that get treated differently if they're unintialized
|
||||
if (glm::any(glm::isnan(result.color.range.start))) {
|
||||
result.color.range.start = getColor();
|
||||
}
|
||||
if (glm::any(glm::isnan(result.color.range.finish))) {
|
||||
result.color.range.finish = getColor();
|
||||
}
|
||||
if (glm::isnan(result.alpha.range.start)) {
|
||||
result.alpha.range.start = getAlpha();
|
||||
}
|
||||
if (glm::isnan(result.alpha.range.finish)) {
|
||||
result.alpha.range.finish = getAlpha();
|
||||
}
|
||||
if (glm::isnan(result.radius.range.start)) {
|
||||
result.radius.range.start = getParticleRadius();
|
||||
}
|
||||
if (glm::isnan(result.radius.range.finish)) {
|
||||
result.radius.range.finish = getParticleRadius();
|
||||
}
|
||||
});
|
||||
|
||||
if (!result.valid()) {
|
||||
qCWarning(entities) << "failed validation";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -19,12 +19,14 @@
|
|||
|
||||
namespace particle {
|
||||
static const float SCRIPT_MAXIMUM_PI = 3.1416f; // Round up so that reasonable property values work
|
||||
static const xColor DEFAULT_COLOR = { 255, 255, 255 };
|
||||
static const xColor DEFAULT_COLOR_SPREAD = { 0, 0, 0 };
|
||||
static const float UNINITIALIZED = NAN;
|
||||
static const vec3 DEFAULT_COLOR = { 255, 255, 255 };
|
||||
static const vec3 DEFAULT_COLOR_UNINITIALIZED = { UNINITIALIZED, UNINITIALIZED, UNINITIALIZED };
|
||||
static const vec3 DEFAULT_COLOR_SPREAD = { 0, 0, 0 };
|
||||
static const float DEFAULT_ALPHA = 1.0f;
|
||||
static const float DEFAULT_ALPHA_SPREAD = 0.0f;
|
||||
static const float DEFAULT_ALPHA_START = DEFAULT_ALPHA;
|
||||
static const float DEFAULT_ALPHA_FINISH = DEFAULT_ALPHA;
|
||||
static const float DEFAULT_ALPHA_START = UNINITIALIZED;
|
||||
static const float DEFAULT_ALPHA_FINISH = UNINITIALIZED;
|
||||
static const float MINIMUM_ALPHA = 0.0f;
|
||||
static const float MAXIMUM_ALPHA = 1.0f;
|
||||
static const quint32 DEFAULT_MAX_PARTICLES = 1000;
|
||||
|
@ -65,8 +67,8 @@ namespace particle {
|
|||
static const float MINIMUM_PARTICLE_RADIUS = 0.0f;
|
||||
static const float MAXIMUM_PARTICLE_RADIUS = (float)TREE_SCALE;
|
||||
static const float DEFAULT_RADIUS_SPREAD = 0.0f;
|
||||
static const float DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS;
|
||||
static const float DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS;
|
||||
static const float DEFAULT_RADIUS_START = UNINITIALIZED;
|
||||
static const float DEFAULT_RADIUS_FINISH = UNINITIALIZED;
|
||||
static const QString DEFAULT_TEXTURES = "";
|
||||
static const bool DEFAULT_EMITTER_SHOULD_TRAIL = false;
|
||||
|
||||
|
@ -145,12 +147,12 @@ namespace particle {
|
|||
};
|
||||
|
||||
struct Properties {
|
||||
RangeGradient<xColor> color{ DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_COLOR_SPREAD };
|
||||
RangeGradient<float> alpha{ DEFAULT_ALPHA, DEFAULT_ALPHA_START, DEFAULT_ALPHA_FINISH, DEFAULT_ALPHA_SPREAD };
|
||||
float radiusStart{ DEFAULT_EMIT_RADIUS_START };
|
||||
RangeGradient<float> radius{ DEFAULT_PARTICLE_RADIUS, DEFAULT_RADIUS_START, DEFAULT_RADIUS_FINISH, DEFAULT_RADIUS_SPREAD };
|
||||
float lifespan{ DEFAULT_LIFESPAN };
|
||||
uint32_t maxParticles{ DEFAULT_MAX_PARTICLES };
|
||||
RangeGradient<vec3> color { DEFAULT_COLOR, DEFAULT_COLOR_UNINITIALIZED, DEFAULT_COLOR_UNINITIALIZED, DEFAULT_COLOR_SPREAD };
|
||||
RangeGradient<float> alpha { DEFAULT_ALPHA, DEFAULT_ALPHA_START, DEFAULT_ALPHA_FINISH, DEFAULT_ALPHA_SPREAD };
|
||||
float radiusStart { DEFAULT_EMIT_RADIUS_START };
|
||||
RangeGradient<float> radius { DEFAULT_PARTICLE_RADIUS, DEFAULT_RADIUS_START, DEFAULT_RADIUS_FINISH, DEFAULT_RADIUS_SPREAD };
|
||||
float lifespan { DEFAULT_LIFESPAN };
|
||||
uint32_t maxParticles { DEFAULT_MAX_PARTICLES };
|
||||
EmitProperties emission;
|
||||
Range<float> polar { DEFAULT_POLAR_START, DEFAULT_POLAR_FINISH };
|
||||
Range<float> azimuth { DEFAULT_AZIMUTH_START, DEFAULT_AZIMUTH_FINISH };
|
||||
|
@ -176,10 +178,10 @@ namespace particle {
|
|||
return *this;
|
||||
}
|
||||
|
||||
glm::vec4 getColorStart() const { return glm::vec4(ColorUtils::sRGBToLinearVec3(toGlm(color.range.start)), alpha.range.start); }
|
||||
glm::vec4 getColorMiddle() const { return glm::vec4(ColorUtils::sRGBToLinearVec3(toGlm(color.gradient.target)), alpha.gradient.target); }
|
||||
glm::vec4 getColorFinish() const { return glm::vec4(ColorUtils::sRGBToLinearVec3(toGlm(color.range.finish)), alpha.range.finish); }
|
||||
glm::vec4 getColorSpread() const { return glm::vec4(ColorUtils::sRGBToLinearVec3(toGlm(color.gradient.spread)), alpha.gradient.spread); }
|
||||
vec4 getColorStart() const { return vec4(ColorUtils::sRGBToLinearVec3(color.range.start / 255.0f), alpha.range.start); }
|
||||
vec4 getColorMiddle() const { return vec4(ColorUtils::sRGBToLinearVec3(color.gradient.target / 255.0f), alpha.gradient.target); }
|
||||
vec4 getColorFinish() const { return vec4(ColorUtils::sRGBToLinearVec3(color.range.finish / 255.0f), alpha.range.finish); }
|
||||
vec4 getColorSpread() const { return vec4(ColorUtils::sRGBToLinearVec3(color.gradient.spread / 255.0f), alpha.gradient.spread); }
|
||||
};
|
||||
} // namespace particles
|
||||
|
||||
|
@ -215,37 +217,29 @@ public:
|
|||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) override;
|
||||
|
||||
const rgbColor& getColor() const { return _particleColorHack; }
|
||||
xColor getXColor() const { return _particleProperties.color.gradient.target; }
|
||||
glm::vec3 getColorRGB() const { return ColorUtils::sRGBToLinearVec3(toGlm(getXColor())); }
|
||||
xColor getXColor() const;
|
||||
vec3 getColor() const { return _particleProperties.color.gradient.target; }
|
||||
|
||||
void setColor(const rgbColor& value);
|
||||
void setColor(const vec3& value);
|
||||
void setColor(const xColor& value);
|
||||
|
||||
bool _isColorStartInitialized = false;
|
||||
void setColorStart(const xColor& colorStart) { _particleProperties.color.range.start = colorStart; _isColorStartInitialized = true; }
|
||||
xColor getColorStart() const { return _isColorStartInitialized ? _particleProperties.color.range.start : getXColor(); }
|
||||
glm::vec3 getColorStartRGB() const { return _isColorStartInitialized ? ColorUtils::sRGBToLinearVec3(toGlm(_particleProperties.color.range.start)) : getColorRGB(); }
|
||||
void setColorStart(const vec3& colorStart);
|
||||
vec3 getColorStart() const { return _particleProperties.color.range.start; }
|
||||
|
||||
bool _isColorFinishInitialized = false;
|
||||
void setColorFinish(const xColor& colorFinish) { _particleProperties.color.range.finish = colorFinish; _isColorFinishInitialized = true; }
|
||||
xColor getColorFinish() const { return _isColorFinishInitialized ? _particleProperties.color.range.finish : getXColor(); }
|
||||
glm::vec3 getColorFinishRGB() const { return _isColorFinishInitialized ? ColorUtils::sRGBToLinearVec3(toGlm(_particleProperties.color.range.finish)) : getColorRGB(); }
|
||||
void setColorFinish(const vec3& colorFinish);
|
||||
vec3 getColorFinish() const { return _particleProperties.color.range.finish; }
|
||||
|
||||
void setColorSpread(const xColor& colorSpread) { _particleProperties.color.gradient.spread = colorSpread; }
|
||||
xColor getColorSpread() const { return _particleProperties.color.gradient.spread; }
|
||||
glm::vec3 getColorSpreadRGB() const { return ColorUtils::sRGBToLinearVec3(toGlm(_particleProperties.color.gradient.spread)); }
|
||||
void setColorSpread(const xColor& colorSpread);
|
||||
xColor getColorSpread() const;
|
||||
|
||||
void setAlpha(float alpha);
|
||||
float getAlpha() const { return _particleProperties.alpha.gradient.target; }
|
||||
|
||||
bool _isAlphaStartInitialized = false;
|
||||
void setAlphaStart(float alphaStart);
|
||||
float getAlphaStart() const { return _isAlphaStartInitialized ? _particleProperties.alpha.range.start : _particleProperties.alpha.gradient.target; }
|
||||
float getAlphaStart() const { return _particleProperties.alpha.range.start; }
|
||||
|
||||
bool _isAlphaFinishInitialized = false;
|
||||
void setAlphaFinish(float alphaFinish);
|
||||
float getAlphaFinish() const { return _isAlphaFinishInitialized ? _particleProperties.alpha.range.finish : _particleProperties.alpha.gradient.target; }
|
||||
float getAlphaFinish() const { return _particleProperties.alpha.range.finish; }
|
||||
|
||||
void setAlphaSpread(float alphaSpread);
|
||||
float getAlphaSpread() const { return _particleProperties.alpha.gradient.spread; }
|
||||
|
@ -303,31 +297,31 @@ public:
|
|||
void setParticleRadius(float particleRadius);
|
||||
float getParticleRadius() const { return _particleProperties.radius.gradient.target; }
|
||||
|
||||
bool _isRadiusStartInitialized = false;
|
||||
void setRadiusStart(float radiusStart);
|
||||
float getRadiusStart() const { return _isRadiusStartInitialized ? _particleProperties.radius.range.start : _particleProperties.radius.gradient.target; }
|
||||
float getRadiusStart() const { return _particleProperties.radius.range.start; }
|
||||
|
||||
bool _isRadiusFinishInitialized = false;
|
||||
void setRadiusFinish(float radiusFinish);
|
||||
float getRadiusFinish() const { return _isRadiusFinishInitialized ? _particleProperties.radius.range.finish : _particleProperties.radius.gradient.target; }
|
||||
float getRadiusFinish() const { return _particleProperties.radius.range.finish; }
|
||||
|
||||
void setRadiusSpread(float radiusSpread);
|
||||
float getRadiusSpread() const { return _particleProperties.radius.gradient.spread; }
|
||||
|
||||
void computeAndUpdateDimensions();
|
||||
|
||||
QString getTextures() const;
|
||||
void setTextures(const QString& textures);
|
||||
QString getTextures() const { return _particleProperties.textures; }
|
||||
|
||||
bool getEmitterShouldTrail() const { return _particleProperties.emission.shouldTrail; }
|
||||
void setEmitterShouldTrail(bool emitterShouldTrail) { _particleProperties.emission.shouldTrail = emitterShouldTrail; }
|
||||
void setEmitterShouldTrail(bool emitterShouldTrail);
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const override { return false; }
|
||||
|
||||
particle::Properties getParticleProperties() const;
|
||||
particle::Properties getParticleProperties() const;
|
||||
|
||||
static const xColor DEFAULT_XCOLOR;
|
||||
static const xColor DEFAULT_XCOLOR_SPREAD;
|
||||
|
||||
protected:
|
||||
rgbColor _particleColorHack;
|
||||
particle::Properties _particleProperties;
|
||||
bool _isEmitting { true };
|
||||
|
||||
|
|
297
libraries/gpu/src/gpu/Noise.slh
Normal file
297
libraries/gpu/src/gpu/Noise.slh
Normal file
|
@ -0,0 +1,297 @@
|
|||
<!
|
||||
// gpu/Noise.slh
|
||||
//
|
||||
// Created by Sam Gondelman on 6/15/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
!>
|
||||
|
||||
// Shader includes portions of webgl-noise:
|
||||
// Description : Array and textureless GLSL 2D/3D/4D simplex
|
||||
// noise functions.
|
||||
// Author : Ian McEwan, Ashima Arts.
|
||||
// Maintainer : ijm
|
||||
// Lastmod : 20110822 (ijm)
|
||||
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
|
||||
// Distributed under the MIT License. See LICENSE file.
|
||||
// https://github.com/ashima/webgl-noise
|
||||
//
|
||||
|
||||
<@if not NOISE_SLH@>
|
||||
<@def NOISE_SLH@>
|
||||
|
||||
float mod289(float x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
vec2 mod289(vec2 x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
vec3 mod289(vec3 x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
vec4 mod289(vec4 x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
float permute(float x) {
|
||||
return mod289(((x*34.0)+1.0)*x);
|
||||
}
|
||||
|
||||
vec3 permute(vec3 x) {
|
||||
return mod289(((x*34.0)+1.0)*x);
|
||||
}
|
||||
|
||||
vec4 permute(vec4 x) {
|
||||
return mod289(((x*34.0)+1.0)*x);
|
||||
}
|
||||
|
||||
float taylorInvSqrt(float r) {
|
||||
return 1.79284291400159 - 0.85373472095314 * r;
|
||||
}
|
||||
|
||||
vec4 taylorInvSqrt(vec4 r) {
|
||||
return 1.79284291400159 - 0.85373472095314 * r;
|
||||
}
|
||||
|
||||
vec4 grad4(float j, vec4 ip) {
|
||||
const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
|
||||
vec4 p, s;
|
||||
|
||||
p.xyz = floor(fract(vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
|
||||
p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
|
||||
s = vec4(lessThan(p, vec4(0.0)));
|
||||
p.xyz = p.xyz + (s.xyz * 2.0 - 1.0) * s.www;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// (sqrt(5) - 1)/4 = F4, used once below
|
||||
#define F4 0.309016994374947451
|
||||
|
||||
float snoise(vec4 v) {
|
||||
const vec4 C = vec4(0.138196601125011, // (5 - sqrt(5))/20 G4
|
||||
0.276393202250021, // 2 * G4
|
||||
0.414589803375032, // 3 * G4
|
||||
-0.447213595499958); // -1 + 4 * G4
|
||||
|
||||
// First corner
|
||||
vec4 i = floor(v + dot(v, vec4(F4)));
|
||||
vec4 x0 = v - i + dot(i, C.xxxx);
|
||||
|
||||
// Other corners
|
||||
|
||||
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
|
||||
vec4 i0;
|
||||
vec3 isX = step(x0.yzw, x0.xxx);
|
||||
vec3 isYZ = step(x0.zww, x0.yyz);
|
||||
i0.x = isX.x + isX.y + isX.z;
|
||||
i0.yzw = 1.0 - isX;
|
||||
i0.y += isYZ.x + isYZ.y;
|
||||
i0.zw += 1.0 - isYZ.xy;
|
||||
i0.z += isYZ.z;
|
||||
i0.w += 1.0 - isYZ.z;
|
||||
|
||||
// i0 now contains the unique values 0,1,2,3 in each channel
|
||||
vec4 i3 = clamp(i0, 0.0, 1.0);
|
||||
vec4 i2 = clamp(i0 - 1.0, 0.0, 1.0);
|
||||
vec4 i1 = clamp(i0 - 2.0, 0.0, 1.0);
|
||||
|
||||
vec4 x1 = x0 - i1 + C.xxxx;
|
||||
vec4 x2 = x0 - i2 + C.yyyy;
|
||||
vec4 x3 = x0 - i3 + C.zzzz;
|
||||
vec4 x4 = x0 + C.wwww;
|
||||
|
||||
// Permutations
|
||||
i = mod289(i);
|
||||
float j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x);
|
||||
vec4 j1 = permute(
|
||||
permute(
|
||||
permute(
|
||||
permute(i.w + vec4(i1.w, i2.w, i3.w, 1.0)) + i.z
|
||||
+ vec4(i1.z, i2.z, i3.z, 1.0)) + i.y
|
||||
+ vec4(i1.y, i2.y, i3.y, 1.0)) + i.x
|
||||
+ vec4(i1.x, i2.x, i3.x, 1.0));
|
||||
|
||||
// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
|
||||
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
|
||||
vec4 ip = vec4(1.0 / 294.0, 1.0 / 49.0, 1.0 / 7.0, 0.0);
|
||||
|
||||
vec4 p0 = grad4(j0, ip);
|
||||
vec4 p1 = grad4(j1.x, ip);
|
||||
vec4 p2 = grad4(j1.y, ip);
|
||||
vec4 p3 = grad4(j1.z, ip);
|
||||
vec4 p4 = grad4(j1.w, ip);
|
||||
|
||||
// Normalise gradients
|
||||
vec4 norm = taylorInvSqrt(
|
||||
vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
|
||||
p0 *= norm.x;
|
||||
p1 *= norm.y;
|
||||
p2 *= norm.z;
|
||||
p3 *= norm.w;
|
||||
p4 *= taylorInvSqrt(dot(p4, p4));
|
||||
|
||||
// Mix contributions from the five corners
|
||||
vec3 m0 = max(0.6 - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)), 0.0);
|
||||
vec2 m1 = max(0.6 - vec2(dot(x3, x3), dot(x4, x4)), 0.0);
|
||||
m0 = m0 * m0;
|
||||
m1 = m1 * m1;
|
||||
return 49.0
|
||||
* (dot(m0 * m0, vec3(dot(p0, x0), dot(p1, x1), dot(p2, x2)))
|
||||
+ dot(m1 * m1, vec2(dot(p3, x3), dot(p4, x4))));
|
||||
|
||||
}
|
||||
|
||||
float snoise(vec3 v) {
|
||||
const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
|
||||
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
|
||||
|
||||
// First corner
|
||||
vec3 i = floor(v + dot(v, C.yyy));
|
||||
vec3 x0 = v - i + dot(i, C.xxx);
|
||||
|
||||
// Other corners
|
||||
vec3 g = step(x0.yzx, x0.xyz);
|
||||
vec3 l = 1.0 - g;
|
||||
vec3 i1 = min(g.xyz, l.zxy);
|
||||
vec3 i2 = max(g.xyz, l.zxy);
|
||||
|
||||
vec3 x1 = x0 - i1 + C.xxx;
|
||||
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
|
||||
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
|
||||
|
||||
// Permutations
|
||||
i = mod289(i);
|
||||
vec4 p = permute(
|
||||
permute(
|
||||
permute(i.z + vec4(0.0, i1.z, i2.z, 1.0)) + i.y
|
||||
+ vec4(0.0, i1.y, i2.y, 1.0)) + i.x
|
||||
+ vec4(0.0, i1.x, i2.x, 1.0));
|
||||
|
||||
// Gradients: 7x7 points over a square, mapped onto an octahedron.
|
||||
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
|
||||
float n_ = 0.142857142857; // 1.0/7.0
|
||||
vec3 ns = n_ * D.wyz - D.xzx;
|
||||
|
||||
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
|
||||
|
||||
vec4 x_ = floor(j * ns.z);
|
||||
vec4 y_ = floor(j - 7.0 * x_); // mod(j,N)
|
||||
|
||||
vec4 x = x_ * ns.x + ns.yyyy;
|
||||
vec4 y = y_ * ns.x + ns.yyyy;
|
||||
vec4 h = 1.0 - abs(x) - abs(y);
|
||||
|
||||
vec4 b0 = vec4(x.xy, y.xy);
|
||||
vec4 b1 = vec4(x.zw, y.zw);
|
||||
|
||||
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
|
||||
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
|
||||
vec4 s0 = floor(b0) * 2.0 + 1.0;
|
||||
vec4 s1 = floor(b1) * 2.0 + 1.0;
|
||||
vec4 sh = -step(h, vec4(0.0));
|
||||
|
||||
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
|
||||
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
|
||||
|
||||
vec3 p0 = vec3(a0.xy, h.x);
|
||||
vec3 p1 = vec3(a0.zw, h.y);
|
||||
vec3 p2 = vec3(a1.xy, h.z);
|
||||
vec3 p3 = vec3(a1.zw, h.w);
|
||||
|
||||
//Normalise gradients
|
||||
vec4 norm = taylorInvSqrt(
|
||||
vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
|
||||
p0 *= norm.x;
|
||||
p1 *= norm.y;
|
||||
p2 *= norm.z;
|
||||
p3 *= norm.w;
|
||||
|
||||
// Mix final noise value
|
||||
vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)),
|
||||
0.0);
|
||||
m = m * m;
|
||||
return 42.0
|
||||
* dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
|
||||
}
|
||||
|
||||
float snoise(vec2 v) {
|
||||
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
|
||||
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
|
||||
-0.577350269189626, // -1.0 + 2.0 * C.x
|
||||
0.024390243902439); // 1.0 / 41.0
|
||||
// First corner
|
||||
vec2 i = floor(v + dot(v, C.yy));
|
||||
vec2 x0 = v - i + dot(i, C.xx);
|
||||
|
||||
// Other corners
|
||||
vec2 i1;
|
||||
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
||||
vec4 x12 = x0.xyxy + C.xxzz;
|
||||
x12.xy -= i1;
|
||||
|
||||
// Permutations
|
||||
i = mod289(i); // Avoid truncation effects in permutation
|
||||
vec3 p = permute(
|
||||
permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));
|
||||
|
||||
vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)),
|
||||
0.0);
|
||||
m = m * m;
|
||||
m = m * m;
|
||||
|
||||
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
|
||||
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
|
||||
|
||||
vec3 x = 2.0 * fract(p * C.www) - 1.0;
|
||||
vec3 h = abs(x) - 0.5;
|
||||
vec3 ox = floor(x + 0.5);
|
||||
vec3 a0 = x - ox;
|
||||
|
||||
// Normalise gradients implicitly by scaling m
|
||||
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
|
||||
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
|
||||
|
||||
// Compute final noise value at P
|
||||
vec3 g;
|
||||
g.x = a0.x * x0.x + h.x * x0.y;
|
||||
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
||||
return 130.0 * dot(m, g);
|
||||
}
|
||||
|
||||
// https://www.shadertoy.com/view/lsfGRr
|
||||
float hifi_hash(float n) {
|
||||
return fract(sin(n) * 43758.5453);
|
||||
}
|
||||
|
||||
float hifi_noise(in vec2 x) {
|
||||
vec2 p = floor(x);
|
||||
vec2 f = fract(x);
|
||||
|
||||
f = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
float n = p.x + p.y * 57.0;
|
||||
|
||||
return mix(mix(hifi_hash(n + 0.0), hifi_hash(n + 1.0), f.x),
|
||||
mix(hifi_hash(n + 57.0), hifi_hash(n + 58.0), f.x), f.y);
|
||||
}
|
||||
|
||||
// https://www.shadertoy.com/view/MdX3Rr
|
||||
// https://en.wikipedia.org/wiki/Fractional_Brownian_motion
|
||||
float hifi_fbm(in vec2 p) {
|
||||
const mat2 m2 = mat2(0.8, -0.6, 0.6, 0.8);
|
||||
float f = 0.0;
|
||||
f += 0.5000 * hifi_noise(p); p = m2 * p * 2.02;
|
||||
f += 0.2500 * hifi_noise(p); p = m2 * p * 2.03;
|
||||
f += 0.1250 * hifi_noise(p); p = m2 * p * 2.01;
|
||||
f += 0.0625 * hifi_noise(p);
|
||||
|
||||
return f / 0.9375;
|
||||
}
|
||||
|
||||
<@endif@>
|
|
@ -422,7 +422,7 @@ bool Geometry::areTexturesLoaded() const {
|
|||
}
|
||||
// Failed texture downloads need to be considered as 'loaded'
|
||||
// or the object will never fade in
|
||||
bool finished = texture->isLoaded() || texture->isFailed();
|
||||
bool finished = texture->isFailed() || (texture->isLoaded() && texture->getGPUTexture() && texture->getGPUTexture()->isDefined());
|
||||
if (!finished) {
|
||||
return true;
|
||||
}
|
||||
|
@ -434,8 +434,11 @@ bool Geometry::areTexturesLoaded() const {
|
|||
}
|
||||
|
||||
// If material textures are loaded, check the material translucency
|
||||
// FIXME: This should not be done here. The opacity map should already be reset in Material::setTextureMap.
|
||||
// However, currently that code can be called before the albedo map is defined, so resetOpacityMap will fail.
|
||||
// Geometry::areTexturesLoaded() is called repeatedly until it returns true, so we do the check here for now
|
||||
const auto albedoTexture = material->_textures[NetworkMaterial::MapChannel::ALBEDO_MAP];
|
||||
if (albedoTexture.texture && albedoTexture.texture->getGPUTexture()) {
|
||||
if (albedoTexture.texture) {
|
||||
material->resetOpacityMap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -706,7 +706,16 @@ void Resource::handleDownloadProgress(uint64_t bytesReceived, uint64_t bytesTota
|
|||
}
|
||||
|
||||
void Resource::handleReplyFinished() {
|
||||
Q_ASSERT_X(_request, "Resource::handleReplyFinished", "Request should not be null while in handleReplyFinished");
|
||||
if (!_request || _request != sender()) {
|
||||
// This can happen in the edge case that a request is timed out, but a `finished` signal is emitted before it is deleted.
|
||||
qWarning(networking) << "Received signal Resource::handleReplyFinished from ResourceRequest that is not the current"
|
||||
<< " request: " << sender() << ", " << _request;
|
||||
PROFILE_ASYNC_END(resource, "Resource:" + getType(), QString::number(_requestID), {
|
||||
{ "from_cache", false },
|
||||
{ "size_mb", _bytesTotal / 1000000.0 }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
PROFILE_ASYNC_END(resource, "Resource:" + getType(), QString::number(_requestID), {
|
||||
{ "from_cache", _request->loadedFromCache() },
|
||||
|
@ -715,15 +724,8 @@ void Resource::handleReplyFinished() {
|
|||
|
||||
setSize(_bytesTotal);
|
||||
|
||||
if (!_request || _request != sender()) {
|
||||
// This can happen in the edge case that a request is timed out, but a `finished` signal is emitted before it is deleted.
|
||||
qWarning(networking) << "Received signal Resource::handleReplyFinished from ResourceRequest that is not the current"
|
||||
<< " request: " << sender() << ", " << _request;
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceCache::requestCompleted(_self);
|
||||
|
||||
|
||||
auto result = _request->getResult();
|
||||
if (result == ResourceRequest::Success) {
|
||||
auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString());
|
||||
|
@ -733,7 +735,7 @@ void Resource::handleReplyFinished() {
|
|||
if (!relativePathURL.isEmpty()) {
|
||||
_effectiveBaseURL = relativePathURL;
|
||||
}
|
||||
|
||||
|
||||
auto data = _request->getData();
|
||||
emit loaded(data);
|
||||
downloadFinished(data);
|
||||
|
|
|
@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
case PacketType::EntityPhysics:
|
||||
return static_cast<PacketVersion>(EntityVersion::YieldSimulationOwnership);
|
||||
return static_cast<PacketVersion>(EntityVersion::ParticleEntityFix);
|
||||
case PacketType::EntityQuery:
|
||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
||||
case PacketType::AvatarIdentity:
|
||||
|
|
|
@ -237,7 +237,8 @@ enum class EntityVersion : PacketVersion {
|
|||
MaterialData,
|
||||
CloneableData,
|
||||
CollisionMask16Bytes,
|
||||
YieldSimulationOwnership
|
||||
YieldSimulationOwnership,
|
||||
ParticleEntityFix
|
||||
};
|
||||
|
||||
enum class EntityScriptCallMethodVersion : PacketVersion {
|
||||
|
|
|
@ -339,7 +339,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
|
||||
if (_numInactiveUpdates > 0) {
|
||||
const uint8_t MAX_NUM_INACTIVE_UPDATES = 20;
|
||||
if (_numInactiveUpdates > MAX_NUM_INACTIVE_UPDATES || isServerlessMode()) {
|
||||
if (_numInactiveUpdates > MAX_NUM_INACTIVE_UPDATES) {
|
||||
// clear local ownership (stop sending updates) and let the server clear itself
|
||||
_entity->clearSimulationOwnership();
|
||||
return false;
|
||||
|
@ -834,9 +834,3 @@ void EntityMotionState::clearObjectVelocities() const {
|
|||
}
|
||||
_entity->setAcceleration(glm::vec3(0.0f));
|
||||
}
|
||||
|
||||
bool EntityMotionState::isServerlessMode() {
|
||||
EntityTreeElementPointer element = _entity->getElement();
|
||||
EntityTreePointer tree = element ? element->getTree() : nullptr;
|
||||
return tree ? tree->isServerlessMode() : false;
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
|
|||
QVariantMap ObjectActionOffset::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["pointToOffsetFrom"] = glmToQMap(_pointToOffsetFrom);
|
||||
arguments["pointToOffsetFrom"] = vec3ToQMap(_pointToOffsetFrom);
|
||||
arguments["linearTimeScale"] = _linearTimeScale;
|
||||
arguments["linearDistance"] = _linearDistance;
|
||||
});
|
||||
|
|
|
@ -333,9 +333,9 @@ QVariantMap ObjectActionTractor::getArguments() {
|
|||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["linearTimeScale"] = _linearTimeScale;
|
||||
arguments["targetPosition"] = glmToQMap(_desiredPositionalTarget);
|
||||
arguments["targetPosition"] = vec3ToQMap(_desiredPositionalTarget);
|
||||
|
||||
arguments["targetRotation"] = glmToQMap(_desiredRotationalTarget);
|
||||
arguments["targetRotation"] = quatToQMap(_desiredRotationalTarget);
|
||||
arguments["angularTimeScale"] = _angularTimeScale;
|
||||
|
||||
arguments["otherID"] = _otherID;
|
||||
|
|
|
@ -161,7 +161,7 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) {
|
|||
QVariantMap ObjectActionTravelOriented::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["forward"] = glmToQMap(_forward);
|
||||
arguments["forward"] = vec3ToQMap(_forward);
|
||||
arguments["angularTimeScale"] = _angularTimeScale;
|
||||
});
|
||||
return arguments;
|
||||
|
|
|
@ -193,9 +193,9 @@ bool ObjectConstraintBallSocket::updateArguments(QVariantMap arguments) {
|
|||
QVariantMap ObjectConstraintBallSocket::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["pivot"] = glmToQMap(_pivotInA);
|
||||
arguments["pivot"] = vec3ToQMap(_pivotInA);
|
||||
arguments["otherEntityID"] = _otherID;
|
||||
arguments["otherPivot"] = glmToQMap(_pivotInB);
|
||||
arguments["otherPivot"] = vec3ToQMap(_pivotInB);
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
|
|
@ -279,11 +279,11 @@ bool ObjectConstraintConeTwist::updateArguments(QVariantMap arguments) {
|
|||
QVariantMap ObjectConstraintConeTwist::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["pivot"] = glmToQMap(_pivotInA);
|
||||
arguments["axis"] = glmToQMap(_axisInA);
|
||||
arguments["pivot"] = vec3ToQMap(_pivotInA);
|
||||
arguments["axis"] = vec3ToQMap(_axisInA);
|
||||
arguments["otherEntityID"] = _otherID;
|
||||
arguments["otherPivot"] = glmToQMap(_pivotInB);
|
||||
arguments["otherAxis"] = glmToQMap(_axisInB);
|
||||
arguments["otherPivot"] = vec3ToQMap(_pivotInB);
|
||||
arguments["otherAxis"] = vec3ToQMap(_axisInB);
|
||||
arguments["swingSpan1"] = _swingSpan1;
|
||||
arguments["swingSpan2"] = _swingSpan2;
|
||||
arguments["twistSpan"] = _twistSpan;
|
||||
|
|
|
@ -264,11 +264,11 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
|
|||
QVariantMap ObjectConstraintHinge::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["pivot"] = glmToQMap(_pivotInA);
|
||||
arguments["axis"] = glmToQMap(_axisInA);
|
||||
arguments["pivot"] = vec3ToQMap(_pivotInA);
|
||||
arguments["axis"] = vec3ToQMap(_axisInA);
|
||||
arguments["otherEntityID"] = _otherID;
|
||||
arguments["otherPivot"] = glmToQMap(_pivotInB);
|
||||
arguments["otherAxis"] = glmToQMap(_axisInB);
|
||||
arguments["otherPivot"] = vec3ToQMap(_pivotInB);
|
||||
arguments["otherAxis"] = vec3ToQMap(_axisInB);
|
||||
arguments["low"] = _low;
|
||||
arguments["high"] = _high;
|
||||
if (_constraint) {
|
||||
|
|
|
@ -289,11 +289,11 @@ bool ObjectConstraintSlider::updateArguments(QVariantMap arguments) {
|
|||
QVariantMap ObjectConstraintSlider::getArguments() {
|
||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
||||
withReadLock([&] {
|
||||
arguments["point"] = glmToQMap(_pointInA);
|
||||
arguments["axis"] = glmToQMap(_axisInA);
|
||||
arguments["point"] = vec3ToQMap(_pointInA);
|
||||
arguments["axis"] = vec3ToQMap(_axisInA);
|
||||
arguments["otherEntityID"] = _otherID;
|
||||
arguments["otherPoint"] = glmToQMap(_pointInB);
|
||||
arguments["otherAxis"] = glmToQMap(_axisInB);
|
||||
arguments["otherPoint"] = vec3ToQMap(_pointInB);
|
||||
arguments["otherAxis"] = vec3ToQMap(_axisInB);
|
||||
arguments["linearLow"] = _linearLow;
|
||||
arguments["linearHigh"] = _linearHigh;
|
||||
arguments["angularLow"] = _angularLow;
|
||||
|
|
|
@ -306,12 +306,15 @@ void PhysicalEntitySimulation::getObjectsToChange(VectorOfMotionStates& result)
|
|||
}
|
||||
|
||||
void PhysicalEntitySimulation::handleDeactivatedMotionStates(const VectorOfMotionStates& motionStates) {
|
||||
bool serverlessMode = getEntityTree()->isServerlessMode();
|
||||
for (auto stateItr : motionStates) {
|
||||
ObjectMotionState* state = &(*stateItr);
|
||||
assert(state);
|
||||
if (state->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
|
||||
entityState->handleDeactivation();
|
||||
if (!serverlessMode) {
|
||||
entityState->handleDeactivation();
|
||||
}
|
||||
EntityItemPointer entity = entityState->getEntity();
|
||||
_entitiesToSort.insert(entity);
|
||||
}
|
||||
|
@ -357,13 +360,7 @@ void PhysicalEntitySimulation::handleChangedMotionStates(const VectorOfMotionSta
|
|||
}
|
||||
|
||||
void PhysicalEntitySimulation::addOwnershipBid(EntityMotionState* motionState) {
|
||||
if (getEntityTree()->isServerlessMode()) {
|
||||
EntityItemPointer entity = motionState->getEntity();
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
auto sessionID = nodeList->getSessionUUID();
|
||||
entity->setSimulationOwner(SimulationOwner(sessionID, SCRIPT_GRAB_SIMULATION_PRIORITY));
|
||||
_owned.push_back(motionState);
|
||||
} else {
|
||||
if (!getEntityTree()->isServerlessMode()) {
|
||||
motionState->initForBid();
|
||||
motionState->sendBid(_entityPacketSender, _physicsEngine->getNumSubsteps());
|
||||
_bids.push_back(motionState);
|
||||
|
@ -372,8 +369,10 @@ void PhysicalEntitySimulation::addOwnershipBid(EntityMotionState* motionState) {
|
|||
}
|
||||
|
||||
void PhysicalEntitySimulation::addOwnership(EntityMotionState* motionState) {
|
||||
motionState->initForOwned();
|
||||
_owned.push_back(motionState);
|
||||
if (!getEntityTree()->isServerlessMode()) {
|
||||
motionState->initForOwned();
|
||||
_owned.push_back(motionState);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalEntitySimulation::sendOwnershipBids(uint32_t numSubsteps) {
|
||||
|
@ -412,6 +411,7 @@ void PhysicalEntitySimulation::sendOwnershipBids(uint32_t numSubsteps) {
|
|||
}
|
||||
|
||||
void PhysicalEntitySimulation::sendOwnedUpdates(uint32_t numSubsteps) {
|
||||
bool serverlessMode = getEntityTree()->isServerlessMode();
|
||||
PROFILE_RANGE_EX(simulation_physics, "Update", 0x00000000, (uint64_t)_owned.size());
|
||||
uint32_t i = 0;
|
||||
while (i < _owned.size()) {
|
||||
|
@ -423,7 +423,7 @@ void PhysicalEntitySimulation::sendOwnedUpdates(uint32_t numSubsteps) {
|
|||
}
|
||||
_owned.remove(i);
|
||||
} else {
|
||||
if (_owned[i]->shouldSendUpdate(numSubsteps)) {
|
||||
if (!serverlessMode && _owned[i]->shouldSendUpdate(numSubsteps)) {
|
||||
_owned[i]->sendUpdate(_entityPacketSender, numSubsteps);
|
||||
}
|
||||
++i;
|
||||
|
|
|
@ -8,292 +8,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// Shader includes portions of webgl-noise:
|
||||
// Description : Array and textureless GLSL 2D/3D/4D simplex
|
||||
// noise functions.
|
||||
// Author : Ian McEwan, Ashima Arts.
|
||||
// Maintainer : ijm
|
||||
// Lastmod : 20110822 (ijm)
|
||||
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
|
||||
// Distributed under the MIT License. See LICENSE file.
|
||||
// https://github.com/ashima/webgl-noise
|
||||
//
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include gpu/Noise.slh@>
|
||||
|
||||
<$declareStandardCameraTransform()$>
|
||||
|
||||
float mod289(float x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
vec2 mod289(vec2 x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
vec3 mod289(vec3 x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
vec4 mod289(vec4 x) {
|
||||
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||||
}
|
||||
|
||||
float permute(float x) {
|
||||
return mod289(((x*34.0)+1.0)*x);
|
||||
}
|
||||
|
||||
vec3 permute(vec3 x) {
|
||||
return mod289(((x*34.0)+1.0)*x);
|
||||
}
|
||||
|
||||
vec4 permute(vec4 x) {
|
||||
return mod289(((x*34.0)+1.0)*x);
|
||||
}
|
||||
|
||||
float taylorInvSqrt(float r) {
|
||||
return 1.79284291400159 - 0.85373472095314 * r;
|
||||
}
|
||||
|
||||
vec4 taylorInvSqrt(vec4 r) {
|
||||
return 1.79284291400159 - 0.85373472095314 * r;
|
||||
}
|
||||
|
||||
vec4 grad4(float j, vec4 ip) {
|
||||
const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
|
||||
vec4 p, s;
|
||||
|
||||
p.xyz = floor(fract(vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
|
||||
p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
|
||||
s = vec4(lessThan(p, vec4(0.0)));
|
||||
p.xyz = p.xyz + (s.xyz * 2.0 - 1.0) * s.www;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// (sqrt(5) - 1)/4 = F4, used once below
|
||||
#define F4 0.309016994374947451
|
||||
|
||||
float snoise(vec4 v) {
|
||||
const vec4 C = vec4(0.138196601125011, // (5 - sqrt(5))/20 G4
|
||||
0.276393202250021, // 2 * G4
|
||||
0.414589803375032, // 3 * G4
|
||||
-0.447213595499958); // -1 + 4 * G4
|
||||
|
||||
// First corner
|
||||
vec4 i = floor(v + dot(v, vec4(F4)));
|
||||
vec4 x0 = v - i + dot(i, C.xxxx);
|
||||
|
||||
// Other corners
|
||||
|
||||
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
|
||||
vec4 i0;
|
||||
vec3 isX = step(x0.yzw, x0.xxx);
|
||||
vec3 isYZ = step(x0.zww, x0.yyz);
|
||||
i0.x = isX.x + isX.y + isX.z;
|
||||
i0.yzw = 1.0 - isX;
|
||||
i0.y += isYZ.x + isYZ.y;
|
||||
i0.zw += 1.0 - isYZ.xy;
|
||||
i0.z += isYZ.z;
|
||||
i0.w += 1.0 - isYZ.z;
|
||||
|
||||
// i0 now contains the unique values 0,1,2,3 in each channel
|
||||
vec4 i3 = clamp(i0, 0.0, 1.0);
|
||||
vec4 i2 = clamp(i0 - 1.0, 0.0, 1.0);
|
||||
vec4 i1 = clamp(i0 - 2.0, 0.0, 1.0);
|
||||
|
||||
vec4 x1 = x0 - i1 + C.xxxx;
|
||||
vec4 x2 = x0 - i2 + C.yyyy;
|
||||
vec4 x3 = x0 - i3 + C.zzzz;
|
||||
vec4 x4 = x0 + C.wwww;
|
||||
|
||||
// Permutations
|
||||
i = mod289(i);
|
||||
float j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x);
|
||||
vec4 j1 = permute(
|
||||
permute(
|
||||
permute(
|
||||
permute(i.w + vec4(i1.w, i2.w, i3.w, 1.0)) + i.z
|
||||
+ vec4(i1.z, i2.z, i3.z, 1.0)) + i.y
|
||||
+ vec4(i1.y, i2.y, i3.y, 1.0)) + i.x
|
||||
+ vec4(i1.x, i2.x, i3.x, 1.0));
|
||||
|
||||
// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
|
||||
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
|
||||
vec4 ip = vec4(1.0 / 294.0, 1.0 / 49.0, 1.0 / 7.0, 0.0);
|
||||
|
||||
vec4 p0 = grad4(j0, ip);
|
||||
vec4 p1 = grad4(j1.x, ip);
|
||||
vec4 p2 = grad4(j1.y, ip);
|
||||
vec4 p3 = grad4(j1.z, ip);
|
||||
vec4 p4 = grad4(j1.w, ip);
|
||||
|
||||
// Normalise gradients
|
||||
vec4 norm = taylorInvSqrt(
|
||||
vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
|
||||
p0 *= norm.x;
|
||||
p1 *= norm.y;
|
||||
p2 *= norm.z;
|
||||
p3 *= norm.w;
|
||||
p4 *= taylorInvSqrt(dot(p4, p4));
|
||||
|
||||
// Mix contributions from the five corners
|
||||
vec3 m0 = max(0.6 - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)), 0.0);
|
||||
vec2 m1 = max(0.6 - vec2(dot(x3, x3), dot(x4, x4)), 0.0);
|
||||
m0 = m0 * m0;
|
||||
m1 = m1 * m1;
|
||||
return 49.0
|
||||
* (dot(m0 * m0, vec3(dot(p0, x0), dot(p1, x1), dot(p2, x2)))
|
||||
+ dot(m1 * m1, vec2(dot(p3, x3), dot(p4, x4))));
|
||||
|
||||
}
|
||||
|
||||
float snoise(vec3 v) {
|
||||
const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);
|
||||
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
|
||||
|
||||
// First corner
|
||||
vec3 i = floor(v + dot(v, C.yyy));
|
||||
vec3 x0 = v - i + dot(i, C.xxx);
|
||||
|
||||
// Other corners
|
||||
vec3 g = step(x0.yzx, x0.xyz);
|
||||
vec3 l = 1.0 - g;
|
||||
vec3 i1 = min(g.xyz, l.zxy);
|
||||
vec3 i2 = max(g.xyz, l.zxy);
|
||||
|
||||
vec3 x1 = x0 - i1 + C.xxx;
|
||||
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
|
||||
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
|
||||
|
||||
// Permutations
|
||||
i = mod289(i);
|
||||
vec4 p = permute(
|
||||
permute(
|
||||
permute(i.z + vec4(0.0, i1.z, i2.z, 1.0)) + i.y
|
||||
+ vec4(0.0, i1.y, i2.y, 1.0)) + i.x
|
||||
+ vec4(0.0, i1.x, i2.x, 1.0));
|
||||
|
||||
// Gradients: 7x7 points over a square, mapped onto an octahedron.
|
||||
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
|
||||
float n_ = 0.142857142857; // 1.0/7.0
|
||||
vec3 ns = n_ * D.wyz - D.xzx;
|
||||
|
||||
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
|
||||
|
||||
vec4 x_ = floor(j * ns.z);
|
||||
vec4 y_ = floor(j - 7.0 * x_); // mod(j,N)
|
||||
|
||||
vec4 x = x_ * ns.x + ns.yyyy;
|
||||
vec4 y = y_ * ns.x + ns.yyyy;
|
||||
vec4 h = 1.0 - abs(x) - abs(y);
|
||||
|
||||
vec4 b0 = vec4(x.xy, y.xy);
|
||||
vec4 b1 = vec4(x.zw, y.zw);
|
||||
|
||||
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
|
||||
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
|
||||
vec4 s0 = floor(b0) * 2.0 + 1.0;
|
||||
vec4 s1 = floor(b1) * 2.0 + 1.0;
|
||||
vec4 sh = -step(h, vec4(0.0));
|
||||
|
||||
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
|
||||
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
|
||||
|
||||
vec3 p0 = vec3(a0.xy, h.x);
|
||||
vec3 p1 = vec3(a0.zw, h.y);
|
||||
vec3 p2 = vec3(a1.xy, h.z);
|
||||
vec3 p3 = vec3(a1.zw, h.w);
|
||||
|
||||
//Normalise gradients
|
||||
vec4 norm = taylorInvSqrt(
|
||||
vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
|
||||
p0 *= norm.x;
|
||||
p1 *= norm.y;
|
||||
p2 *= norm.z;
|
||||
p3 *= norm.w;
|
||||
|
||||
// Mix final noise value
|
||||
vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)),
|
||||
0.0);
|
||||
m = m * m;
|
||||
return 42.0
|
||||
* dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
|
||||
}
|
||||
|
||||
float snoise(vec2 v) {
|
||||
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
|
||||
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
|
||||
-0.577350269189626, // -1.0 + 2.0 * C.x
|
||||
0.024390243902439); // 1.0 / 41.0
|
||||
// First corner
|
||||
vec2 i = floor(v + dot(v, C.yy));
|
||||
vec2 x0 = v - i + dot(i, C.xx);
|
||||
|
||||
// Other corners
|
||||
vec2 i1;
|
||||
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
||||
vec4 x12 = x0.xyxy + C.xxzz;
|
||||
x12.xy -= i1;
|
||||
|
||||
// Permutations
|
||||
i = mod289(i); // Avoid truncation effects in permutation
|
||||
vec3 p = permute(
|
||||
permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));
|
||||
|
||||
vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)),
|
||||
0.0);
|
||||
m = m * m;
|
||||
m = m * m;
|
||||
|
||||
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
|
||||
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
|
||||
|
||||
vec3 x = 2.0 * fract(p * C.www) - 1.0;
|
||||
vec3 h = abs(x) - 0.5;
|
||||
vec3 ox = floor(x + 0.5);
|
||||
vec3 a0 = x - ox;
|
||||
|
||||
// Normalise gradients implicitly by scaling m
|
||||
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
|
||||
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
|
||||
|
||||
// Compute final noise value at P
|
||||
vec3 g;
|
||||
g.x = a0.x * x0.x + h.x * x0.y;
|
||||
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
||||
return 130.0 * dot(m, g);
|
||||
}
|
||||
|
||||
// https://www.shadertoy.com/view/lsfGRr
|
||||
float hifi_hash(float n) {
|
||||
return fract(sin(n) * 43758.5453);
|
||||
}
|
||||
|
||||
float hifi_noise(in vec2 x) {
|
||||
vec2 p = floor(x);
|
||||
vec2 f = fract(x);
|
||||
|
||||
f = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
float n = p.x + p.y * 57.0;
|
||||
|
||||
return mix(mix(hifi_hash(n + 0.0), hifi_hash(n + 1.0), f.x),
|
||||
mix(hifi_hash(n + 57.0), hifi_hash(n + 58.0), f.x), f.y);
|
||||
}
|
||||
|
||||
// https://www.shadertoy.com/view/MdX3Rr
|
||||
// https://en.wikipedia.org/wiki/Fractional_Brownian_motion
|
||||
float hifi_fbm(in vec2 p) {
|
||||
const mat2 m2 = mat2(0.8, -0.6, 0.6, 0.8);
|
||||
float f = 0.0;
|
||||
f += 0.5000 * hifi_noise(p); p = m2 * p * 2.02;
|
||||
f += 0.2500 * hifi_noise(p); p = m2 * p * 2.03;
|
||||
f += 0.1250 * hifi_noise(p); p = m2 * p * 2.01;
|
||||
f += 0.0625 * hifi_noise(p);
|
||||
|
||||
return f / 0.9375;
|
||||
}
|
||||
|
||||
#define PROCEDURAL 1
|
||||
|
||||
//PROCEDURAL_VERSION
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
#include "QVariantGLM.h"
|
||||
#include "OctalCode.h"
|
||||
|
||||
QVariantList glmToQList(const glm::vec3& g) {
|
||||
QVariantList vec3ToQList(const glm::vec3& g) {
|
||||
return QVariantList() << g[0] << g[1] << g[2];
|
||||
}
|
||||
|
||||
QVariantList glmToQList(const glm::quat& g) {
|
||||
QVariantList quatToQList(const glm::quat& g) {
|
||||
return QVariantList() << g.x << g.y << g.z << g.w;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ QVariantList rgbColorToQList(const rgbColor& v) {
|
|||
return QVariantList() << (int)(v[0]) << (int)(v[1]) << (int)(v[2]);
|
||||
}
|
||||
|
||||
QVariantMap glmToQMap(const glm::vec3& glmVector) {
|
||||
QVariantMap vec3ToQMap(const glm::vec3& glmVector) {
|
||||
QVariantMap vectorAsVariantMap;
|
||||
vectorAsVariantMap["x"] = glmVector.x;
|
||||
vectorAsVariantMap["y"] = glmVector.y;
|
||||
|
@ -32,7 +32,7 @@ QVariantMap glmToQMap(const glm::vec3& glmVector) {
|
|||
return vectorAsVariantMap;
|
||||
}
|
||||
|
||||
QVariantMap glmToQMap(const glm::quat& glmQuat) {
|
||||
QVariantMap quatToQMap(const glm::quat& glmQuat) {
|
||||
QVariantMap quatAsVariantMap;
|
||||
quatAsVariantMap["x"] = glmQuat.x;
|
||||
quatAsVariantMap["y"] = glmQuat.y;
|
||||
|
@ -42,12 +42,12 @@ QVariantMap glmToQMap(const glm::quat& glmQuat) {
|
|||
}
|
||||
|
||||
|
||||
glm::vec3 qListToGlmVec3(const QVariant& q) {
|
||||
glm::vec3 qListToVec3(const QVariant& q) {
|
||||
QVariantList qList = q.toList();
|
||||
return glm::vec3(qList[RED_INDEX].toFloat(), qList[GREEN_INDEX].toFloat(), qList[BLUE_INDEX].toFloat());
|
||||
}
|
||||
|
||||
glm::quat qListToGlmQuat(const QVariant& q) {
|
||||
glm::quat qListToQuat(const QVariant& q) {
|
||||
QVariantList qList = q.toList();
|
||||
float x = qList[0].toFloat();
|
||||
float y = qList[1].toFloat();
|
||||
|
@ -56,7 +56,7 @@ glm::quat qListToGlmQuat(const QVariant& q) {
|
|||
return glm::quat(w, x, y, z);
|
||||
}
|
||||
|
||||
void qListtoRgbColor(const QVariant& q, rgbColor& returnValue) {
|
||||
void qListToRgbColor(const QVariant& q, rgbColor& returnValue) {
|
||||
QVariantList qList = q.toList();
|
||||
returnValue[RED_INDEX] = qList[RED_INDEX].toInt();
|
||||
returnValue[GREEN_INDEX] = qList[GREEN_INDEX].toInt();
|
||||
|
@ -64,7 +64,7 @@ void qListtoRgbColor(const QVariant& q, rgbColor& returnValue) {
|
|||
}
|
||||
|
||||
|
||||
glm::vec3 qMapToGlmVec3(const QVariant& q) {
|
||||
glm::vec3 qMapToVec3(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("x") && qMap.contains("y") && qMap.contains("z")) {
|
||||
return glm::vec3(
|
||||
|
@ -77,7 +77,7 @@ glm::vec3 qMapToGlmVec3(const QVariant& q) {
|
|||
}
|
||||
}
|
||||
|
||||
glm::quat qMapToGlmQuat(const QVariant& q) {
|
||||
glm::quat qMapToQuat(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("w") && qMap.contains("x") && qMap.contains("y") && qMap.contains("z")) {
|
||||
return glm::quat(
|
||||
|
@ -91,7 +91,7 @@ glm::quat qMapToGlmQuat(const QVariant& q) {
|
|||
}
|
||||
}
|
||||
|
||||
glm::mat4 qMapToGlmMat4(const QVariant& q) {
|
||||
glm::mat4 qMapToMat4(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("r0c0") && qMap.contains("r1c0") && qMap.contains("r2c0") && qMap.contains("r3c0")
|
||||
&& qMap.contains("r0c1") && qMap.contains("r1c1") && qMap.contains("r2c1") && qMap.contains("r3c1")
|
||||
|
|
|
@ -17,17 +17,17 @@
|
|||
|
||||
#include "SharedUtil.h"
|
||||
|
||||
QVariantList glmToQList(const glm::vec3& g);
|
||||
QVariantList glmToQList(const glm::quat& g);
|
||||
QVariantList vec3ToQList(const glm::vec3& g);
|
||||
QVariantList quatToQList(const glm::quat& g);
|
||||
QVariantList rgbColorToQList(const rgbColor& v);
|
||||
|
||||
QVariantMap glmToQMap(const glm::vec3& glmVector);
|
||||
QVariantMap glmToQMap(const glm::quat& glmQuat);
|
||||
QVariantMap vec3ToQMap(const glm::vec3& glmVector);
|
||||
QVariantMap quatToQMap(const glm::quat& glmQuat);
|
||||
|
||||
glm::vec3 qListToGlmVec3(const QVariant& q);
|
||||
glm::quat qListToGlmQuat(const QVariant& q);
|
||||
void qListtoRgbColor(const QVariant& q, rgbColor& returnValue);
|
||||
glm::vec3 qListToVec3(const QVariant& q);
|
||||
glm::quat qListToQuat(const QVariant& q);
|
||||
void qListToRgbColor(const QVariant& q, rgbColor& returnValue);
|
||||
|
||||
glm::vec3 qMapToGlmVec3(const QVariant& q);
|
||||
glm::quat qMapToGlmQuat(const QVariant& q);
|
||||
glm::mat4 qMapToGlmMat4(const QVariant& q);
|
||||
glm::vec3 qMapToVec3(const QVariant& q);
|
||||
glm::quat qMapToQuat(const QVariant& q);
|
||||
glm::mat4 qMapToMat4(const QVariant& q);
|
||||
|
|
|
@ -127,13 +127,28 @@ QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3) {
|
|||
obj.setProperty("x", vec3.x);
|
||||
obj.setProperty("y", vec3.y);
|
||||
obj.setProperty("z", vec3.z);
|
||||
obj.setProperty("red", vec3.x);
|
||||
obj.setProperty("green", vec3.y);
|
||||
obj.setProperty("blue", vec3.z);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) {
|
||||
vec3.x = object.property("x").toVariant().toFloat();
|
||||
vec3.y = object.property("y").toVariant().toFloat();
|
||||
vec3.z = object.property("z").toVariant().toFloat();
|
||||
auto x = object.property("x").toVariant();
|
||||
if (!x.isValid()) {
|
||||
x = object.property("red").toVariant();
|
||||
}
|
||||
auto y = object.property("y").toVariant();
|
||||
if (!y.isValid()) {
|
||||
y = object.property("green").toVariant();
|
||||
}
|
||||
auto z = object.property("z").toVariant();
|
||||
if (!z.isValid()) {
|
||||
z = object.property("blue").toVariant();
|
||||
}
|
||||
vec3.x = x.toFloat();
|
||||
vec3.y = y.toFloat();
|
||||
vec3.z = z.toFloat();
|
||||
}
|
||||
|
||||
QVariant vec3toVariant(const glm::vec3& vec3) {
|
||||
|
|
|
@ -92,6 +92,8 @@ inline QDebug& operator<<(QDebug& dbg, const rgbColor& c) {
|
|||
}
|
||||
|
||||
struct xColor {
|
||||
xColor() {}
|
||||
xColor(unsigned char r, unsigned char g, unsigned char b) : red(r), green(g), blue(b) {}
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
|
|
|
@ -50,21 +50,29 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
return this.hand === RIGHT_HAND ? leftOverlayLaserInput : rightOverlayLaserInput;
|
||||
};
|
||||
|
||||
this.isPointingAtWebEntity = function(controllerData) {
|
||||
this.isPointingAtTabletOrWeb = function(controllerData, triggerPressed) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
var entityProperty = Entities.getEntityProperties(intersection.objectID);
|
||||
var entityType = entityProperty.type;
|
||||
if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web")) {
|
||||
return true;
|
||||
if (intersection.type === Picks.INTERSECTED_OVERLAY) {
|
||||
var objectID = intersection.objectID;
|
||||
if ((HMD.tabletID && objectID === HMD.tabletID) ||
|
||||
(HMD.tabletScreenID && objectID === HMD.tabletScreenID) ||
|
||||
(HMD.homeButtonID && objectID === HMD.homeButtonID)) {
|
||||
return true;
|
||||
} else {
|
||||
var overlayType = Overlays.getOverlayType(objectID);
|
||||
if (overlayType === "web3d") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (intersection.type === Picks.INTERSECTED_ENTITY) {
|
||||
var entityProperty = Entities.getEntityProperties(intersection.objectID);
|
||||
var entityType = entityProperty.type;
|
||||
var isLocked = entityProperty.locked;
|
||||
return entityType === "Web" && (!isLocked || triggerPressed);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.isPointingAtOverlay = function(controllerData) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
return intersection.type === Picks.INTERSECTED_OVERLAY;
|
||||
};
|
||||
|
||||
this.deleteContextOverlay = function() {
|
||||
var farGrabModule = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||
? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity");
|
||||
|
@ -92,10 +100,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.isReady = function(controllerData) {
|
||||
var otherModuleRunning = this.getOtherModule().running;
|
||||
otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand.
|
||||
var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE
|
||||
&& controllerData.triggerValues[this.otherHand] <= TRIGGER_OFF_VALUE;
|
||||
if ((!otherModuleRunning || isTriggerPressed)
|
||||
&& (this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData))) {
|
||||
var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE &&
|
||||
controllerData.triggerValues[this.otherHand] <= TRIGGER_OFF_VALUE;
|
||||
var allowThisModule = !otherModuleRunning || isTriggerPressed;
|
||||
if (allowThisModule && this.isPointingAtTabletOrWeb(controllerData, isTriggerPressed)) {
|
||||
this.updateAllwaysOn();
|
||||
if (isTriggerPressed) {
|
||||
this.dominantHandOverride = true; // Override dominant hand.
|
||||
|
@ -113,9 +121,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand.
|
||||
otherModuleRunning = otherModuleRunning || this.getOtherModule().dominantHandOverride; // Override dominant hand.
|
||||
var grabModuleNeedsToRun = this.grabModuleWantsNearbyOverlay(controllerData);
|
||||
if (!otherModuleRunning && !grabModuleNeedsToRun && (controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE
|
||||
|| this.parameters.handLaser.allwaysOn
|
||||
&& (this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData)))) {
|
||||
var allowThisModule = !otherModuleRunning && !grabModuleNeedsToRun;
|
||||
var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE;
|
||||
var laserOn = isTriggerPressed || this.parameters.handLaser.allwaysOn;
|
||||
if (allowThisModule && (laserOn && this.isPointingAtTabletOrWeb(controllerData, isTriggerPressed))) {
|
||||
this.running = true;
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ and If there is any changes to either the Entities or properties of
|
|||
**/
|
||||
|
||||
var RADIANS_PER_DEGREE = Math.PI / 180;
|
||||
var DEBOUNCE_TIMEOUT = 125;
|
||||
|
||||
var roundFloat = function (input, round) {
|
||||
round = round ? round : 1000;
|
||||
|
@ -60,13 +61,14 @@ function HifiEntityUI(parent) {
|
|||
this.parent = parent;
|
||||
|
||||
var self = this;
|
||||
this.settingsUpdateLock = false;
|
||||
this.webBridgeSync = _.debounce(function (id, val) {
|
||||
if (self.EventBridge) {
|
||||
if (self.EventBridge && !self.settingsUpdateLock) {
|
||||
var sendPackage = {};
|
||||
sendPackage[id] = val;
|
||||
self.submitChanges(sendPackage);
|
||||
}
|
||||
}, 125);
|
||||
}, DEBOUNCE_TIMEOUT);
|
||||
}
|
||||
|
||||
HifiEntityUI.prototype = {
|
||||
|
@ -112,7 +114,6 @@ HifiEntityUI.prototype = {
|
|||
var self = this;
|
||||
var json = {};
|
||||
var keys = Object.keys(self.builtRows);
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var el = self.builtRows[key];
|
||||
|
@ -144,23 +145,31 @@ HifiEntityUI.prototype = {
|
|||
vector.z = z.value;
|
||||
}
|
||||
json[key] = vector;
|
||||
} else if (el.className.indexOf("radian") !== -1) {
|
||||
json[key] = document.getElementById(key).value * RADIANS_PER_DEGREE;
|
||||
} else if (el.className.length > 0) {
|
||||
json[key] = document.getElementById(key)
|
||||
.value;
|
||||
json[key] = document.getElementById(key).value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return json;
|
||||
},
|
||||
fillFields: function (currentProperties) {
|
||||
var self = this;
|
||||
var fields = document.getElementsByTagName("input");
|
||||
|
||||
self.settingsUpdateLock = true;
|
||||
if (!currentProperties.locked) {
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
fields[i].removeAttribute("disabled");
|
||||
if (fields[i].hasAttribute("data-max")) {
|
||||
// Reset Max to original max
|
||||
fields[i].setAttribute("max", fields[i].getAttribute("data-max"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.onSelect) {
|
||||
self.onSelect();
|
||||
}
|
||||
|
@ -226,6 +235,10 @@ HifiEntityUI.prototype = {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Now unlocking settings Update lock for sending messages on callbacks.
|
||||
setTimeout(function () {
|
||||
self.settingsUpdateLock = false;
|
||||
}, DEBOUNCE_TIMEOUT * 2.5);
|
||||
},
|
||||
connect: function (EventBridge) {
|
||||
this.EventBridge = EventBridge;
|
||||
|
@ -242,6 +255,25 @@ HifiEntityUI.prototype = {
|
|||
if (data.messageType === 'particle_settings') {
|
||||
// Update settings
|
||||
var currentProperties = data.currentProperties;
|
||||
// Update uninitialized variables
|
||||
if (!currentProperties.alphaStart) {
|
||||
currentProperties.alphaStart = currentProperties.alpha;
|
||||
}
|
||||
if (!currentProperties.alphaFinish) {
|
||||
currentProperties.alphaFinish = currentProperties.alpha;
|
||||
}
|
||||
if (!currentProperties.radiusStart) {
|
||||
currentProperties.radiusStart = currentProperties.particleRadius;
|
||||
}
|
||||
if (!currentProperties.radiusFinish) {
|
||||
currentProperties.radiusFinish = currentProperties.particleRadius;
|
||||
}
|
||||
if (!currentProperties.colorStart || !currentProperties.colorStart.red) {
|
||||
currentProperties.colorStart = currentProperties.color;
|
||||
}
|
||||
if (!currentProperties.colorFinish || !currentProperties.colorFinish.red) {
|
||||
currentProperties.colorFinish = currentProperties.color;
|
||||
}
|
||||
self.fillFields(currentProperties);
|
||||
// Do expected property match with structure;
|
||||
} else if (data.messageType === 'particle_close') {
|
||||
|
@ -272,7 +304,7 @@ HifiEntityUI.prototype = {
|
|||
title.innerHTML = section;
|
||||
title.appendChild(dropDown);
|
||||
sectionDivHeader.appendChild(title);
|
||||
|
||||
|
||||
var collapsed = index !== 0;
|
||||
|
||||
dropDown.innerHTML = collapsed ? "L" : "M";
|
||||
|
@ -505,13 +537,13 @@ HifiEntityUI.prototype = {
|
|||
textureImage.classList.remove("no-preview");
|
||||
textureImage.classList.add("no-texture");
|
||||
}
|
||||
self.webBridgeSync(group.id, url);
|
||||
}, 250);
|
||||
}, DEBOUNCE_TIMEOUT * 2);
|
||||
|
||||
textureUrl.oninput = function (event) {
|
||||
// Add throttle
|
||||
var url = event.target.value;
|
||||
imageLoad(url);
|
||||
self.webBridgeSync(group.id, url);
|
||||
};
|
||||
textureUrl.onchange = textureUrl.oninput;
|
||||
textureImage.appendChild(image);
|
||||
|
@ -540,21 +572,21 @@ HifiEntityUI.prototype = {
|
|||
|
||||
slider.setAttribute("min", group.min !== undefined ? group.min : 0);
|
||||
slider.setAttribute("max", group.max !== undefined ? group.max : 10000);
|
||||
slider.setAttribute("data-max", group.max !== undefined ? group.max : 10000);
|
||||
slider.setAttribute("step", 1);
|
||||
|
||||
inputField.oninput = function (event) {
|
||||
|
||||
// TODO: Remove this functionality? Alan finds it confusing
|
||||
if (parseInt(event.target.value) > parseInt(slider.getAttribute("max")) && group.max !== 1) {
|
||||
slider.setAttribute("max", event.target.value);
|
||||
}
|
||||
slider.value = event.target.value;
|
||||
|
||||
self.webBridgeSync(group.id, slider.value);
|
||||
};
|
||||
inputField.onchange = inputField.oninput;
|
||||
slider.oninput = function (event) {
|
||||
inputField.value = event.target.value;
|
||||
self.webBridgeSync(group.id, slider.value);
|
||||
self.webBridgeSync(group.id, inputField.value);
|
||||
};
|
||||
|
||||
inputField.id = group.id;
|
||||
|
@ -579,7 +611,7 @@ HifiEntityUI.prototype = {
|
|||
} else {
|
||||
inputField.value = Math.ceil(event.target.value);
|
||||
}
|
||||
self.webBridgeSync(group.id, slider.value * RADIANS_PER_DEGREE);
|
||||
self.webBridgeSync(group.id, inputField.value * RADIANS_PER_DEGREE);
|
||||
};
|
||||
var degrees = document.createElement("label");
|
||||
degrees.innerHTML = "°";
|
||||
|
@ -596,9 +628,11 @@ HifiEntityUI.prototype = {
|
|||
|
||||
slider.setAttribute("min", group.min !== undefined ? group.min : 0);
|
||||
slider.setAttribute("max", group.max !== undefined ? group.max : 1);
|
||||
slider.setAttribute("data-max", group.max !== undefined ? group.max : 1);
|
||||
slider.setAttribute("step", 0.01);
|
||||
|
||||
inputField.oninput = function (event) {
|
||||
// TODO: Remove this functionality? Alan finds it confusing
|
||||
if (parseFloat(event.target.value) > parseFloat(slider.getAttribute("max")) && group.max !== 1) {
|
||||
slider.setAttribute("max", event.target.value);
|
||||
}
|
||||
|
@ -690,4 +724,4 @@ HifiEntityUI.prototype = {
|
|||
}
|
||||
return row;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -152,6 +152,12 @@
|
|||
type: "SliderFloat",
|
||||
max: 5
|
||||
},
|
||||
{
|
||||
id: "speedSpread",
|
||||
name: "Speed Spread",
|
||||
type: "SliderFloat",
|
||||
max: 5
|
||||
},
|
||||
{
|
||||
type: "Row"
|
||||
},
|
||||
|
|
|
@ -59,6 +59,25 @@ ParticleExplorerTool = function() {
|
|||
}
|
||||
}
|
||||
|
||||
var optionalProps = ["alphaStart", "alphaFinish", "radiusStart", "radiusFinish", "colorStart", "colorFinish"];
|
||||
var fallbackProps = ["alpha", "particleRadius", "color"];
|
||||
var entityProps = Entities.getEntityProperties(that.activeParticleProperties, optionalProps);
|
||||
var needsUpdate = false;
|
||||
for (var i = 0; i < optionalProps.length; i++) {
|
||||
var fallback = fallbackProps[Math.floor(i / 2)];
|
||||
if (data.updatedSettings[fallback]) {
|
||||
var prop = optionalProps[i];
|
||||
if (!that.activeParticleProperties[prop] || (fallback === "color" && !that.activeParticleProperties[prop].red)) {
|
||||
that.activeParticleProperties[prop] = entityProps[fallback];
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needsUpdate) {
|
||||
sendActiveParticleProperties();
|
||||
}
|
||||
|
||||
} else if (data.messageType === "page_loaded") {
|
||||
sendActiveParticleProperties();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue