22 #include <unordered_map>
23 #include <unordered_set>
27 #include <DependencyManager.h>
28 #include <GeometryUtil.h>
29 #include <gpu/Batch.h>
30 #include <render/Forward.h>
31 #include <render/Scene.h>
32 #include <graphics-scripting/Forward.h>
33 #include <Transform.h>
34 #include <SpatiallyNestable.h>
35 #include <TriangleSet.h>
36 #include <DualQuaternion.h>
38 #include "RenderHifi.h"
39 #include "GeometryCache.h"
40 #include "TextureCache.h"
42 #include "PrimitiveMode.h"
43 #include "BillboardMode.h"
44 #include "MirrorMode.h"
57 typedef unsigned int ItemID;
59 class MeshPartPayload;
60 class ModelMeshPartPayload;
61 class ModelRenderLocations;
63 inline uint qHash(
const std::shared_ptr<MeshPartPayload>& a, uint seed) {
64 return qHash(a.get(), seed);
68 using ModelPointer = std::shared_ptr<Model>;
69 using ModelWeakPointer = std::weak_ptr<Model>;
71 struct SortedTriangleSet {
72 SortedTriangleSet(
float distance, TriangleSet* triangleSet,
int partIndex,
int shapeID,
int subMeshIndex) :
73 distance(distance), triangleSet(triangleSet), partIndex(partIndex), shapeID(shapeID), subMeshIndex(subMeshIndex) {}
76 TriangleSet* triangleSet;
82 using BlendShapeOperator = std::function<void(
int,
const QVector<BlendshapeOffset>&,
const QVector<int>&,
const render::ItemIDs&)>;
85 class Model :
public QObject,
public std::enable_shared_from_this<Model>,
public scriptable::ModelProvider {
90 typedef RenderArgs::RenderMode RenderMode;
94 Model(QObject* parent =
nullptr, SpatiallyNestable* spatiallyNestableOverride =
nullptr, uint64_t created = 0);
97 inline ModelPointer getThisPointer()
const {
98 return std::static_pointer_cast<Model>(std::const_pointer_cast<Model>(shared_from_this()));
103 Q_INVOKABLE
virtual void setURL(
const QUrl& url);
104 const QUrl& getURL()
const {
return _url; }
107 void setVisibleInScene(
bool isVisible,
const render::ScenePointer& scene =
nullptr);
108 bool isVisible()
const;
110 render::hifi::Tag getTagMask()
const;
111 void setTagMask(uint8_t mask,
const render::ScenePointer& scene =
nullptr);
113 bool isGroupCulled()
const;
114 void setGroupCulled(
bool isGroupCulled,
const render::ScenePointer& scene =
nullptr);
116 bool canCastShadow()
const;
117 void setCanCastShadow(
bool canCastShadow,
const render::ScenePointer& scene =
nullptr);
119 void setHifiRenderLayer(render::hifi::Layer layer,
const render::ScenePointer& scene =
nullptr);
121 bool isCauterized()
const {
return _cauterized; }
122 void setCauterized(
bool value,
const render::ScenePointer& scene =
nullptr);
124 void setPrimitiveMode(PrimitiveMode primitiveMode,
const render::ScenePointer& scene =
nullptr);
125 PrimitiveMode getPrimitiveMode()
const {
return _primitiveMode; }
127 void setBillboardMode(BillboardMode billboardMode,
const render::ScenePointer& scene =
nullptr);
128 BillboardMode getBillboardMode()
const {
return _billboardMode; }
130 void setCullWithParent(
bool value,
const render::ScenePointer& scene =
nullptr);
132 void setRenderWithZones(
const QVector<QUuid>& renderWithZones,
const render::ScenePointer& scene =
nullptr);
133 const QVector<QUuid>& getRenderWithZones()
const {
return _renderWithZones; }
135 void setMirrorMode(MirrorMode mirrorMode,
const render::ScenePointer& scene =
nullptr);
136 MirrorMode getMirrorMode()
const {
return _mirrorMode; }
138 void setPortalExitID(
const QUuid& portalExitID,
const render::ScenePointer& scene =
nullptr);
139 const QUuid& getPortalExitID()
const {
return _portalExitID; }
142 const render::ItemKey getRenderItemKeyGlobalFlags()
const;
144 bool needsFixupInScene()
const;
146 bool needsReload()
const {
return _needsReload; }
147 bool addToScene(
const render::ScenePointer& scene,
148 render::Transaction& transaction) {
149 auto getters = render::Item::Status::Getters(0);
150 return addToScene(scene, transaction, getters);
152 bool addToScene(
const render::ScenePointer& scene,
153 render::Transaction& transaction,
154 BlendShapeOperator modelBlendshapeOperator) {
155 auto getters = render::Item::Status::Getters(0);
156 return addToScene(scene, transaction, getters, modelBlendshapeOperator);
158 bool addToScene(
const render::ScenePointer& scene,
159 render::Transaction& transaction,
160 render::Item::Status::Getters& statusGetters,
161 BlendShapeOperator modelBlendshapeOperator =
nullptr);
162 void removeFromScene(
const render::ScenePointer& scene, render::Transaction& transaction);
163 bool isRenderable()
const;
165 void updateRenderItemsKey(
const render::ScenePointer& scene);
167 virtual void updateRenderItems();
168 void setRenderItemsNeedUpdate();
169 bool getRenderItemsNeedUpdate() {
return _renderItemsNeedUpdate; }
170 AABox getRenderableMeshBound()
const;
171 const render::ItemIDs& fetchRenderItemIDs()
const;
173 bool maybeStartBlender();
175 bool isLoaded()
const {
return (
bool)_renderGeometry && _renderGeometry->isHFMModelLoaded(); }
176 bool isAddedToScene()
const {
return _addedToScene; }
180 void setSnapModelToRegistrationPoint(
bool snapModelToRegistrationPoint,
const glm::vec3& registrationPoint);
184 virtual void simulate(
float deltaTime,
bool fullUpdate =
true);
185 virtual void updateClusterMatrices();
186 virtual void updateBlendshapes();
189 const Geometry::Pointer&
getGeometry()
const {
return _renderGeometry; }
191 const QVariantMap getTextures()
const { assert(isLoaded());
return _renderGeometry->getTextures(); }
192 Q_INVOKABLE
virtual void setTextures(
const QVariantMap& textures);
197 const MaterialMapping& getMaterialMapping()
const { assert(isLoaded());
return _renderGeometry->getMaterialMapping(); }
199 bool didVisualGeometryRequestFail()
const {
return _visualGeometryRequestFailed; }
201 glm::mat4 getWorldToHFMMatrix()
const;
203 QStringList getJointNames()
const;
206 void setJointState(
int index,
bool valid,
const glm::quat& rotation,
const glm::vec3& translation,
float priority);
207 void setJointRotation(
int index,
bool valid,
const glm::quat& rotation,
float priority);
208 void setJointTranslation(
int index,
bool valid,
const glm::vec3& translation,
float priority);
210 bool findRayIntersectionAgainstSubMeshes(
const glm::vec3& origin,
const glm::vec3& direction,
const glm::vec3& viewFrustumPos,
211 float& distance, BoxFace& face, glm::vec3& surfaceNormal,
212 QVariantMap& extraInfo,
bool pickAgainstTriangles =
false,
bool allowBackface =
false);
213 bool findParabolaIntersectionAgainstSubMeshes(
const glm::vec3& origin,
const glm::vec3& velocity,
const glm::vec3& acceleration,
214 const glm::vec3& viewFrustumPos,
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,
215 QVariantMap& extraInfo,
bool pickAgainstTriangles =
false,
bool allowBackface =
false);
217 void setOffset(
const glm::vec3& offset);
218 const glm::vec3& getOffset()
const {
return _offset; }
219 glm::vec3 getOriginalOffset()
const;
221 void setScaleToFit(
bool scaleToFit,
float largestDimension = 0.0f,
bool forceRescale =
false);
222 void setScaleToFit(
bool scaleToFit,
const glm::vec3& dimensions,
bool forceRescale =
false);
223 bool getScaleToFit()
const {
return _scaleToFit; }
226 setSnapModelToRegistrationPoint(snapModelToCenter, glm::vec3(0.5f,0.5f,0.5f));
228 bool getSnapModelToCenter() {
234 bool getJointPositionInWorldFrame(
int jointIndex, glm::vec3& position)
const;
235 bool getJointRotationInWorldFrame(
int jointIndex, glm::quat& rotation)
const;
241 bool getJointTranslation(
int jointIndex, glm::vec3& translation)
const;
244 bool getAbsoluteJointRotationInRigFrame(
int jointIndex, glm::quat& rotationOut)
const;
245 bool getAbsoluteJointTranslationInRigFrame(
int jointIndex, glm::vec3& translationOut)
const;
247 bool getRelativeDefaultJointRotation(
int jointIndex, glm::quat& rotationOut)
const;
248 bool getRelativeDefaultJointTranslation(
int jointIndex, glm::vec3& translationOut)
const;
262 void setTranslation(
const glm::vec3& translation);
263 void setRotation(
const glm::quat& rotation);
264 void overrideModelTransformAndOffset(
const Transform& transform,
const glm::vec3& offset);
265 bool isOverridingModelTransformAndOffset() {
return _overrideModelTransform; };
266 void stopTransformAndOffsetOverride() { _overrideModelTransform =
false; };
267 void setTransformNoUpdateRenderItems(
const Transform& transform);
269 const glm::vec3& getTranslation()
const {
return _translation; }
270 const glm::quat& getRotation()
const {
return _rotation; }
271 const glm::vec3& getOverrideTranslation()
const {
return _overrideTranslation; }
272 const glm::quat& getOverrideRotation()
const {
return _overrideRotation; }
274 glm::vec3 getNaturalDimensions()
const;
276 Transform getTransform()
const;
278 void setScale(
const glm::vec3& scale);
279 const glm::vec3& getScale()
const {
return _scale; }
286 float getBlendshapeCoefficient(
int index)
const {
287 return ((index < 0) && (index >= _blendshapeCoefficients.size())) ? 0.0f : _blendshapeCoefficients.at(index);
290 Rig& getRig() {
return _rig; }
291 const Rig& getRig()
const {
return _rig; }
296 virtual bool updateGeometry();
298 void setLoadingPriorityOperator(std::function<
float()> priorityOperator) { _loadingPriorityOperator = priorityOperator; }
300 size_t getRenderInfoVertexCount()
const {
return _renderInfoVertexCount; }
301 size_t getRenderInfoTextureSize();
302 int getRenderInfoTextureCount();
303 int getRenderInfoDrawCalls()
const {
return _renderInfoDrawCalls; }
304 bool getRenderInfoHasTransparent()
const {
return _renderInfoHasTransparent; }
306 class TransformDualQuaternion {
308 TransformDualQuaternion() {}
309 TransformDualQuaternion(
const glm::mat4& m) {
311 _scale.x = p.scale().x;
312 _scale.y = p.scale().y;
313 _scale.z = p.scale().z;
315 _dq = DualQuaternion(p.rot(), p.trans());
317 TransformDualQuaternion(
const glm::vec3& scale,
const glm::quat& rot,
const glm::vec3& trans) {
322 _dq = DualQuaternion(rot, trans);
324 TransformDualQuaternion(
const Transform& transform) {
325 _scale = glm::vec4(transform.getScale(), 0.0f);
327 _dq = DualQuaternion(transform.getRotation(), transform.getTranslation());
329 glm::vec3 getScale()
const {
return glm::vec3(_scale); }
330 glm::quat getRotation()
const {
return _dq.getRotation(); }
331 glm::vec3 getTranslation()
const {
return _dq.getTranslation(); }
332 glm::mat4 getMatrix()
const {
return createMatFromScaleQuatAndPos(getScale(), getRotation(), getTranslation()); };
334 void setCauterizationParameters(
float cauterizationAmount,
const glm::vec3& cauterizedPosition) {
335 _scale.w = cauterizationAmount;
336 _cauterizedPosition = glm::vec4(cauterizedPosition, 1.0f);
339 glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f };
341 glm::vec4 _cauterizedPosition { 0.0f, 0.0f, 0.0f, 1.0f };
346 std::vector<TransformDualQuaternion> clusterDualQuaternions;
347 std::vector<glm::mat4> clusterMatrices;
350 const MeshState& getMeshState(
int index) {
return _meshStates.at(index); }
352 const QMap<render::ItemID, render::PayloadPointer>& getRenderItems()
const {
return _modelMeshRenderItemsMap; }
353 BlendShapeOperator getModelBlendshapeOperator()
const {
return _modelBlendshapeOperator; }
355 void renderDebugMeshBoxes(gpu::Batch& batch,
bool forward);
357 int getResourceDownloadAttempts() {
return _renderWatcher.getResourceDownloadAttempts(); }
358 int getResourceDownloadAttemptsRemaining() {
return _renderWatcher.getResourceDownloadAttemptsRemaining(); }
360 Q_INVOKABLE MeshProxyList getMeshes()
const;
361 virtual scriptable::ScriptableModelBase getScriptableModel()
override;
362 virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model,
int meshIndex,
int partIndex)
override;
365 void snapToRegistrationPoint();
366 bool getUseDualQuaternionSkinning()
const {
return _useDualQuaternionSkinning; }
367 void setUseDualQuaternionSkinning(
bool value);
369 void addMaterial(graphics::MaterialLayer material,
const std::string& parentMaterialName);
370 void removeMaterial(graphics::MaterialPointer material,
const std::string& parentMaterialName);
372 void setBlendshapeCoefficients(
const QVector<float>& coefficients) { _blendshapeCoefficients = coefficients; }
374 std::set<std::pair<uint, std::string>> getMeshIDsAndMaterialNamesFromMaterialID(QString parentMaterialName);
377 void loadURLFinished(
bool success);
380 void setURLFinished(
bool success);
381 void setCollisionModelURLFinished(
bool success);
382 void requestRenderUpdate();
388 std::unordered_map<unsigned int, quint16> _priorityMap;
389 std::unordered_map<unsigned int, std::vector<graphics::MaterialLayer>> _materialMapping;
390 std::mutex _materialMappingMutex;
391 void applyMaterialMapping();
393 const QVector<float>& getBlendshapeCoefficients()
const {
return _blendshapeCoefficients; }
403 Geometry::Pointer _renderGeometry;
405 GeometryResourceWatcher _renderWatcher;
407 SpatiallyNestable* _spatiallyNestableOverride;
409 glm::vec3 _translation;
411 glm::vec3 _scale { 1.0f };
413 glm::vec3 _overrideTranslation;
414 glm::quat _overrideRotation;
421 static float FAKE_DIMENSION_PLACEHOLDER;
432 std::vector<MeshState> _meshStates;
434 virtual void initJointStates();
436 void setScaleInternal(
const glm::vec3& scale);
438 virtual void updateRig(
float deltaTime, glm::mat4 parentTransform);
442 _triangleSetsValid =
false;
446 virtual void onInvalidate() {};
448 virtual void deleteGeometry();
452 BlendShapeOperator _modelBlendshapeOperator {
nullptr };
453 QVector<float> _blendshapeCoefficients;
454 QVector<float> _blendedBlendshapeCoefficients;
455 int _blendNumber { 0 };
457 mutable QRecursiveMutex _mutex;
459 bool _overrideModelTransform {
false };
460 bool _triangleSetsValid {
false };
461 void calculateTriangleSets(
const HFMModel& hfmModel);
462 std::vector<std::vector<TriangleSet>> _modelSpaceMeshTriangleSets;
464 virtual void createRenderItemSet();
466 PrimitiveMode _primitiveMode { PrimitiveMode::SOLID };
467 BillboardMode _billboardMode { BillboardMode::NONE };
468 bool _useDualQuaternionSkinning {
false };
471 int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID;
475 QVector<std::shared_ptr<ModelMeshPartPayload>> _modelMeshRenderItems;
476 QMap<render::ItemID, render::PayloadPointer> _modelMeshRenderItemsMap;
477 render::ItemIDs _modelMeshRenderItemIDs;
478 using ShapeInfo =
struct {
int meshIndex; };
479 std::vector<ShapeInfo> _modelMeshRenderItemShapes;
480 std::vector<std::string> _modelMeshMaterialNames;
482 bool _addedToScene {
false };
483 bool _needsFixupInScene {
true };
484 bool _needsReload {
true };
485 bool _needsUpdateClusterMatrices {
true };
486 QVariantMap _pendingTextures { };
488 friend class ModelMeshPartPayload;
491 bool _visualGeometryRequestFailed {
false };
493 bool _renderItemsNeedUpdate {
false };
495 size_t _renderInfoVertexCount { 0 };
496 int _renderInfoTextureCount { 0 };
497 size_t _renderInfoTextureSize { 0 };
498 bool _hasCalculatedTextureInfo {
false };
499 int _renderInfoDrawCalls { 0 };
500 int _renderInfoHasTransparent {
false };
511 render::ItemKey _renderItemKeyGlobalFlags;
512 bool _cauterized {
false };
513 bool _cullWithParent {
false };
514 QVector<QUuid> _renderWithZones;
515 MirrorMode _mirrorMode { MirrorMode::NONE };
518 bool shouldInvalidatePayloadShapeKey(
int meshIndex);
523 std::function<float()> _loadingPriorityOperator { []() {
return 0.0f; } };
525 void calculateTextureInfo();
528 Q_DECLARE_METATYPE(ModelPointer)
529 Q_DECLARE_METATYPE(Geometry::WeakPointer)
530 Q_DECLARE_METATYPE(BlendshapeOffset)
532 class ModelBlender :
public QObject,
public Dependency {
540 void noteRequiresBlend(ModelPointer model);
542 bool shouldComputeBlendshapes() {
return _computeBlendshapes; }
545 void setBlendedVertices(ModelPointer model,
int blendNumber, QVector<BlendshapeOffset> blendshapeOffsets, QVector<int> blendedMeshSizes);
546 void setComputeBlendshapes(
bool computeBlendshapes) { _computeBlendshapes = computeBlendshapes; }
549 using Mutex = std::mutex;
550 using Lock = std::unique_lock<Mutex>;
553 virtual ~ModelBlender();
555 std::queue<ModelWeakPointer> _modelsRequiringBlendsQueue;
556 std::set<ModelWeakPointer, std::owner_less<ModelWeakPointer>> _modelsRequiringBlendsSet;
557 int _pendingBlenders;
560 bool _computeBlendshapes {
true };
Interface provided by Application to other objects that need access to the current view state details...
Definition: AbstractViewStateInterface.h:31
A generic 3D model displaying geometry loaded from a URL.
Definition: Model.h:85
const HFMModel & getHFMModel() const
Provided as a convenience, will crash if !isLoaded()
Definition: Model.h:196
bool _snappedToRegistrationPoint
is the model's offset automatically adjusted to a registration point in model space
Definition: Model.h:428
glm::vec3 _scaleToFitDimensions
If you set scaleToFit, we will calculate scale based on MeshExtents.
Definition: Model.h:424
bool _forceOffset
the point in model space our center is snapped to
Definition: Model.h:430
Extents getBindExtents() const
Returns the extents of the model in its bind pose.
Definition: Model.cpp:1252
Extents getUnscaledMeshExtents() const
Returns the unscaled extents of the model's mesh.
Definition: Model.cpp:1271
bool getJointPosition(int jointIndex, glm::vec3 &position) const
Definition: Model.cpp:1366
void clearJointState(int index)
Clear the joint states.
Definition: Model.cpp:1287
glm::vec3 getScaleToFitDimensions() const
is model scaled to fit
Definition: Model.cpp:1446
bool getIsScaledToFit() const
enables/disables scale to fit behavior, the model will be automatically scaled to the specified large...
Definition: Model.h:282
const Geometry::Pointer & getGeometry() const
Returns a reference to the shared geometry.
Definition: Model.h:189
bool _snapModelToRegistrationPoint
have we scaled to fit
Definition: Model.h:427
Extents getMeshExtents() const
Returns the extents of the model's mesh.
Definition: Model.cpp:1266
int getBlendshapeCoefficientsNum() const
the dimensions model is scaled to, including inferred y/z
Definition: Model.h:285
void setJointState(int index, bool valid, const glm::quat &rotation, const glm::vec3 &translation, float priority)
Sets the joint state at the specified index.
Definition: Model.cpp:1291
glm::vec3 _registrationPoint
are we currently snapped to a registration point
Definition: Model.h:429
void setSnapModelToCenter(bool snapModelToCenter)
is scale to fit enabled
Definition: Model.h:225
bool getJointRotation(int jointIndex, glm::quat &rotation) const
Definition: Model.cpp:1374
int getJointStateCount() const
Returns the number of joint states in the model.
Definition: Model.h:233
void invalidCalculatedMeshBoxes()
Allow sub classes to force invalidating the bboxes.
Definition: Model.h:441
virtual Q_INVOKABLE void setURL(const QUrl &url)
Sets the URL of the model to render.
Definition: Model.cpp:1317
bool _scaledToFit
this is the dimensions that scale to fit will use
Definition: Model.h:425
int getParentJointIndex(int jointIndex) const
Returns the index of the parent of the indexed joint, or -1 if not found.
Definition: Model.cpp:1303
The runtime model format.
Definition: HFM.h:305