diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index b7afc3ed9e..b4042cf294 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -16,6 +16,7 @@ link_hifi_libraries( controllers physics plugins midi image material-networking model-networking ktx shaders ) +include_hifi_library_headers(procedural) add_dependencies(${TARGET_NAME} oven) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 36fd04681a..c7ab810c9a 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -512,10 +512,10 @@ void AvatarMixer::handleAvatarKilled(SharedNodePointer avatarNode) { // we relay avatar kill packets to agents that are not upstream // and downstream avatar mixers, if the node that was just killed was being replicatedConnectedAgent return node->getActiveSocket() && - ((node->getType() == NodeType::Agent && !node->isUpstream()) || + (((node->getType() == NodeType::Agent || node->getType() == NodeType::EntityScriptServer) && !node->isUpstream()) || (avatarNode->isReplicated() && shouldReplicateTo(*avatarNode, *node))); }, [&](const SharedNodePointer& node) { - if (node->getType() == NodeType::Agent) { + if (node->getType() == NodeType::Agent || node->getType() == NodeType::EntityScriptServer) { if (!killPacket) { killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true); killPacket->write(avatarNode->getUUID().toRfc4122()); diff --git a/interface/resources/avatar/animations/sitting_idle_aimoffsets.fbx b/interface/resources/avatar/animations/sitting_idle_aimoffsets.fbx new file mode 100644 index 0000000000..275efc88fb Binary files /dev/null and b/interface/resources/avatar/animations/sitting_idle_aimoffsets.fbx differ diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index 670c520b65..cfcf1cff73 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -594,86 +594,1285 @@ "children": [ { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 271, + "loopFlag": true, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_talk02.fbx" + }, + "id": "seatedTalk02", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 252, + "loopFlag": true, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_talk03.fbx" + }, + "id": "seatedTalk03", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 442, + "loopFlag": true, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_talk04.fbx" + }, + "id": "seatedTalk04", + "type": "clip" + } ], "data": { - "endFrame": 271, - "loopFlag": true, + "currentState": "seatedTalk02", + "randomSwitchTimeMax": 12, + "randomSwitchTimeMin": 7, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedTalk02", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedTalk03", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedTalk04", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + } + ], + "triggerRandomSwitch": "seatedTalkSwitch" + }, + "id": "seatedTalk", + "type": "randomSwitchStateMachine" + }, + { + "children": [ + { + "children": [ + { + "children": [ + ], + "data": { + "endFrame": 800, + "loopFlag": true, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle.fbx" + }, + "id": "seatedIdle01", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 800, + "loopFlag": true, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle02.fbx" + }, + "id": "seatedIdle02", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 800, + "loopFlag": true, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle03.fbx" + }, + "id": "seatedIdle03", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 800, + "loopFlag": true, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle04.fbx" + }, + "id": "seatedIdle04", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 332, + "loopFlag": true, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle05.fbx" + }, + "id": "seatedIdle05", + "type": "clip" + } + ], + "data": { + "currentState": "seatedIdle01", + "endFrame": 30, + "randomSwitchTimeMax": 40, + "randomSwitchTimeMin": 10, + "startFrame": 10, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedIdle01", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedIdle02", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedIdle03", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedIdle04", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedIdle05", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": 1, + "resume": true, + "transitions": [ + ] + } + ], + "timeScale": 1, + "triggerRandomSwitch": "seatedIdleSwitch", + "triggerTimeMax": 10 + }, + "id": "masterSeatedIdle", + "type": "randomSwitchStateMachine" + }, + { + "children": [ + { + "children": [ + ], + "data": { + "endFrame": 744, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_shifting.fbx" + }, + "id": "seatedFidgetShifting", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 420, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_lookfidget.fbx" + }, + "id": "seatedFidgetLookFidget", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 282, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_shiftweight.fbx" + }, + "id": "seatedFidgetShiftWeight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 428, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_fidget.fbx" + }, + "id": "seatedFidgeting", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 324, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_lookaround.fbx" + }, + "id": "seatedFidgetLookAround", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 120, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_lookleftright.fbx" + }, + "id": "seatedFidgetLookLeftRight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 178, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_leanforward.fbx" + }, + "id": "seatedFidgetLeanForward", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 140, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_once_shakelegs.fbx" + }, + "id": "seatedFidgetShakeLegs", + "type": "clip" + } + ], + "data": { + "currentState": "seatedFidgetShifting", + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedFidgetShifting", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidgetLookFidget", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidgetShiftWeight", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidgeting", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidgetLookAround", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidgetLookLeftRight", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidgetLeanForward", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidgetShakeLegs", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + } + ] + }, + "id": "seatedFidget", + "type": "randomSwitchStateMachine" + } + ], + "data": { + "currentState": "masterSeatedIdle", + "randomSwitchTimeMax": 20, + "randomSwitchTimeMin": 10, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "masterSeatedIdle", + "interpDuration": 20, + "interpTarget": 20, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedFidget", + "var": "timeToSeatedFidget" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedFidget", + "interpDuration": 30, + "interpTarget": 30, + "interpType": "evaluateBoth", + "priority": -1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetShiftingOnDone" + }, + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetLookFidgetOnDone" + }, + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetShiftWeightOnDone" + }, + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetingOnDone" + }, + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetLookAroundOnDone" + }, + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetLookLeftRightOnDone" + }, + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetLeanForwardOnDone" + }, + { + "randomSwitchState": "masterSeatedIdle", + "var": "seatedFidgetShakeLegsOnDone" + } + ] + } + ], + "transitionVar": "timeToSeatedFidget", + "triggerRandomSwitch": "", + "triggerTimeMax": 45, + "triggerTimeMin": 10 + }, + "id": "seatedIdle", + "type": "randomSwitchStateMachine" + } + ], + "data": { + "alpha": 1, + "alphaVar": "talkOverlayAlpha", + "boneSet": "upperBody" + }, + "id": "seatedTalkOverlay", + "type": "overlay" + }, + { + "children": [ + { + "children": [ + ], + "data": { + "endFrame": 44, + "loopFlag": false, "startFrame": 1, "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_talk02.fbx" + "url": "qrc:///avatar/animations/sitting_emote_agree_headnod.fbx" }, - "id": "seatedTalk02", + "id": "seatedReactionPositiveHeadNod", "type": "clip" }, { "children": [ ], "data": { - "endFrame": 252, - "loopFlag": true, + "endFrame": 78, + "loopFlag": false, "startFrame": 1, "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_talk03.fbx" + "url": "qrc:///avatar/animations/sitting_emote_agree_headnodyes.fbx" }, - "id": "seatedTalk03", + "id": "seatedReactionPositiveHeadNodYes", "type": "clip" }, { "children": [ ], "data": { - "endFrame": 442, - "loopFlag": true, - "startFrame": 0, + "endFrame": 65, + "loopFlag": false, + "startFrame": 1, "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_talk04.fbx" + "url": "qrc:///avatar/animations/sitting_emote_agree_longheadnod.fbx" }, - "id": "seatedTalk04", + "id": "seatedReactionPositiveLongHeadNod", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 78, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_agree_cheer.fbx" + }, + "id": "seatedReactionPositiveCheer", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 64, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_agree_acknowledge.fbx" + }, + "id": "seatedReactionPositiveAcknowledge", "type": "clip" } ], "data": { - "currentState": "seatedTalk02", + "currentState": "seatedReactionPositiveHeadNod", + "endFrame": 30, + "loopFlag": false, "randomSwitchTimeMax": 12, "randomSwitchTimeMin": 7, + "startFrame": 0, "states": [ { - "easingType": "easeInOutQuad", - "id": "seatedTalk02", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", + "id": "seatedReactionPositiveHeadNod", + "interpDuration": 1, + "interpTarget": 1, "priority": 1, - "resume": true, + "resume": false, "transitions": [ ] }, { - "easingType": "easeInOutQuad", - "id": "seatedTalk03", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", + "id": "seatedReactionPositiveHeadNodYes", + "interpDuration": 1, + "interpTarget": 1, "priority": 1, - "resume": true, + "resume": false, "transitions": [ ] }, { - "easingType": "easeInOutQuad", - "id": "seatedTalk04", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", + "id": "seatedReactionPositiveLongHeadNod", + "interpDuration": 1, + "interpTarget": 1, "priority": 1, - "resume": true, + "resume": false, + "transitions": [ + ] + }, + { + "id": "seatedReactionPositiveCheer", + "interpDuration": 1, + "interpTarget": 1, + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "id": "seatedReactionPositiveAcknowledge", + "interpDuration": 1, + "interpTarget": 1, + "priority": 1, + "resume": false, "transitions": [ ] } ], - "triggerRandomSwitch": "seatedTalkSwitch" + "timeScale": 1, + "triggerRandomSwitch": "", + "url": "qrc:///avatar/animations/sitting_idle.fbx" }, - "id": "seatedTalk", + "id": "seatedReactionPositive", + "type": "randomSwitchStateMachine" + }, + { + "children": [ + { + "children": [ + ], + "data": { + "endFrame": 64, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_disagree_headshake.fbx" + }, + "id": "seatedReactionNegativeDisagreeHeadshake", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 99, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_disagree_drophead.fbx" + }, + "id": "seatedReactionNegativeDisagreeDropHead", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 124, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_disagree_disbelief.fbx" + }, + "id": "seatedReactionNegativeDisagreeDisbelief", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 70, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_disagree_dismiss.fbx" + }, + "id": "seatedReactionNegativeDisagreeDismiss", + "type": "clip" + } + ], + "data": { + "currentState": "seatedReactionNegativeDisagreeHeadshake", + "endFrame": 30, + "loopFlag": false, + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "startFrame": 0, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedReactionNegativeDisagreeHeadshake", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionNegativeDisagreeDropHead", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionNegativeDisagreeDisbelief", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionNegativeDisagreeDismiss", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + ] + } + ], + "timeScale": 1, + "triggerRandomSwitch": "", + "url": "qrc:///avatar/animations/sitting_idle.fbx" + }, + "id": "seatedReactionNegative", + "type": "randomSwitchStateMachine" + }, + { + "children": [ + { + "children": [ + ], + "data": { + "endFrame": 32, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" + }, + "id": "seatedReactionRaiseHandIntro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 345, + "loopFlag": true, + "startFrame": 32, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" + }, + "id": "seatedReactionRaiseHandLoop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 400, + "loopFlag": false, + "startFrame": 345, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" + }, + "id": "seatedReactionRaiseHandOutro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 18, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand02_all.fbx" + }, + "id": "seatedReactionRaiseHand02Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 378, + "loopFlag": true, + "startFrame": 18, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand02_all.fbx" + }, + "id": "seatedReactionRaiseHand02Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 435, + "loopFlag": false, + "startFrame": 378, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand02_all.fbx" + }, + "id": "seatedReactionRaiseHand02Outro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 15, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand03_all.fbx" + }, + "id": "seatedReactionRaiseHand03Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 233, + "loopFlag": true, + "mirrorFlag": false, + "startFrame": 15, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand03_all.fbx" + }, + "id": "seatedReactionRaiseHand03Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 296, + "loopFlag": false, + "mirrorFlag": false, + "startFrame": 233, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_raisehand03_all.fbx" + }, + "id": "seatedReactionRaiseHand03Outro", + "type": "clip" + } + ], + "data": { + "currentState": "seatedReactionRaiseHandIntro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHandIntro", + "interpDuration": 8, + "interpTarget": 9, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHandLoop", + "var": "seatedReactionRaiseHandIntroOnDone" + } + ] + }, + { + "id": "seatedReactionRaiseHandLoop", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHandOutro", + "var": "reactionRaiseHandDisabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHandOutro", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHandLoop", + "var": "reactionRaiseHandEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHand02Intro", + "interpDuration": 8, + "interpTarget": 8, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHand02Loop", + "var": "seatedReactionRaiseHand02IntroOnDone" + } + ] + }, + { + "id": "seatedReactionRaiseHand02Loop", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHand02Outro", + "var": "reactionRaiseHandDisabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHand02Outro", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHand02Loop", + "var": "reactionRaiseHandEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHand03Intro", + "interpDuration": 8, + "interpTarget": 8, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHand03Loop", + "var": "seatedReactionRaiseHand03IntroOnDone" + } + ] + }, + { + "id": "seatedReactionRaiseHand03Loop", + "interpDuration": 1, + "interpTarget": 1, + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHand03Outro", + "var": "reactionRaiseHandDisabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHand03Outro", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionRaiseHand03Loop", + "var": "reactionRaiseHandEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" + }, + "id": "seatedReactionRaiseHand", + "type": "randomSwitchStateMachine" + }, + { + "children": [ + { + "children": [ + ], + "data": { + "endFrame": 12, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" + }, + "id": "seatedReactionApplaudIntro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 76, + "loopFlag": true, + "startFrame": 12, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" + }, + "id": "seatedReactionApplaudLoop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 99, + "loopFlag": false, + "startFrame": 76, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" + }, + "id": "seatedReactionApplaudOutro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 12, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap02_all.fbx" + }, + "id": "seatedReactionApplaud02Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 112, + "loopFlag": true, + "startFrame": 12, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap02_all.fbx" + }, + "id": "seatedReactionApplaud02Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 132, + "loopFlag": false, + "startFrame": 112, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap02_all.fbx" + }, + "id": "seatedReactionApplaud02Outro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 17, + "loopFlag": false, + "startFrame": 0, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap03_all.fbx" + }, + "id": "seatedReactionApplaud03Intro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 111, + "loopFlag": true, + "startFrame": 17, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap03_all.fbx" + }, + "id": "seatedReactionApplaud03Loop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 136, + "loopFlag": false, + "startFrame": 111, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_clap03_all.fbx" + }, + "id": "seatedReactionApplaud03Outro", + "type": "clip" + } + ], + "data": { + "currentState": "seatedReactionApplaudIntro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaudIntro", + "interpDuration": 8, + "interpTarget": 8, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaudLoop", + "var": "seatedReactionApplaudIntroOnDone" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaudLoop", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaudOutro", + "var": "reactionApplaudDisabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaudOutro", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaudLoop", + "var": "reactionApplaudEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaud02Intro", + "interpDuration": 8, + "interpTarget": 8, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaud02Loop", + "var": "seatedReactionApplaud02IntroOnDone" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaud02Loop", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaud02Outro", + "var": "reactionApplaudDisabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaud02Outro", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaud02Loop", + "var": "reactionApplaudEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaud03Intro", + "interpDuration": 8, + "interpTarget": 8, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaud03Loop", + "var": "seatedReactionApplaud03IntroOnDone" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaud03Loop", + "interpDuration": 1, + "interpTarget": 1, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaud03Outro", + "var": "reactionApplaudDisabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaud03Outro", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionApplaud03Loop", + "var": "reactionApplaudEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" + }, + "id": "seatedReactionApplaud", "type": "randomSwitchStateMachine" }, { @@ -682,139 +1881,111 @@ "children": [ { "children": [ + { + "children": [ + ], + "data": { + "endFrame": 21, + "loopFlag": false, + "startFrame": 1, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + }, + "id": "seatedReactionPointIntro", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 100, + "loopFlag": true, + "startFrame": 21, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + }, + "id": "seatedReactionPointLoop", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "endFrame": 134, + "loopFlag": false, + "mirrorFlag": false, + "startFrame": 100, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + }, + "id": "seatedReactionPointOutro", + "type": "clip" + } ], "data": { - "endFrame": 800, - "loopFlag": true, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle.fbx" + "currentState": "seatedReactionPointIntro", + "randomSwitchTimeMax": 10, + "randomSwitchTimeMin": 1, + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedReactionPointIntro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 1, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionPointLoop", + "var": "seatedReactionPointIntroOnDone" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionPointLoop", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionPointOutro", + "var": "reactionPointDisabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionPointOutro", + "interpDuration": 18, + "interpTarget": 18, + "interpType": "evaluateBoth", + "priority": 0, + "resume": false, + "transitions": [ + { + "randomSwitchState": "seatedReactionPointLoop", + "var": "reactionPointEnabled" + } + ] + } + ], + "triggerRandomSwitch": "" }, - "id": "seatedIdle01", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 800, - "loopFlag": true, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle02.fbx" - }, - "id": "seatedIdle02", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 800, - "loopFlag": true, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle03.fbx" - }, - "id": "seatedIdle03", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 800, - "loopFlag": true, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle04.fbx" - }, - "id": "seatedIdle04", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 332, - "loopFlag": true, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle05.fbx" - }, - "id": "seatedIdle05", - "type": "clip" + "id": "seatedReactionPoint", + "type": "randomSwitchStateMachine" } ], "data": { - "currentState": "seatedIdle01", - "endFrame": 30, - "randomSwitchTimeMax": 40, - "randomSwitchTimeMin": 10, - "startFrame": 10, - "states": [ - { - "easingType": "easeInOutQuad", - "id": "seatedIdle01", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", - "priority": 1, - "resume": true, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedIdle02", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", - "priority": 1, - "resume": true, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedIdle03", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", - "priority": 1, - "resume": true, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedIdle04", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", - "priority": 1, - "resume": true, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedIdle05", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", - "priority": 1, - "resume": true, - "transitions": [ - ] - } - ], - "timeScale": 1, - "triggerRandomSwitch": "seatedIdleSwitch", - "triggerTimeMax": 10 + "alpha": 0, + "alphaVar": "seatedPointBlendAlpha", + "blendType": "addAbsolute" }, - "id": "masterSeatedIdle", - "type": "randomSwitchStateMachine" + "id": "seatedReactionPointBase", + "type": "blendLinear" }, { "children": [ @@ -822,1555 +1993,562 @@ "children": [ ], "data": { - "endFrame": 744, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_shifting.fbx" - }, - "id": "seatedFidgetShifting", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 420, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_lookfidget.fbx" - }, - "id": "seatedFidgetLookFidget", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 282, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_shiftweight.fbx" - }, - "id": "seatedFidgetShiftWeight", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 428, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_fidget.fbx" - }, - "id": "seatedFidgeting", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 324, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_lookaround.fbx" - }, - "id": "seatedFidgetLookAround", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 120, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_lookleftright.fbx" - }, - "id": "seatedFidgetLookLeftRight", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 178, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_leanforward.fbx" - }, - "id": "seatedFidgetLeanForward", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 140, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_idle_once_shakelegs.fbx" - }, - "id": "seatedFidgetShakeLegs", - "type": "clip" - } - ], - "data": { - "currentState": "seatedFidgetShifting", - "states": [ - { - "easingType": "easeInOutQuad", - "id": "seatedFidgetShifting", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidgetLookFidget", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidgetShiftWeight", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidgeting", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidgetLookAround", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidgetLookLeftRight", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidgetLeanForward", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidgetShakeLegs", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - } - ] - }, - "id": "seatedFidget", - "type": "randomSwitchStateMachine" - } - ], - "data": { - "currentState": "masterSeatedIdle", - "randomSwitchTimeMax": 20, - "randomSwitchTimeMin": 10, - "states": [ - { - "easingType": "easeInOutQuad", - "id": "masterSeatedIdle", - "interpDuration": 20, - "interpTarget": 20, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedFidget", - "var": "timeToSeatedFidget" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedFidget", - "interpDuration": 30, - "interpTarget": 30, - "interpType": "evaluateBoth", - "priority": -1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetShiftingOnDone" - }, - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetLookFidgetOnDone" - }, - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetShiftWeightOnDone" - }, - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetingOnDone" - }, - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetLookAroundOnDone" - }, - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetLookLeftRightOnDone" - }, - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetLeanForwardOnDone" - }, - { - "randomSwitchState": "masterSeatedIdle", - "var": "seatedFidgetShakeLegsOnDone" - } - ] - } - ], - "transitionVar": "timeToSeatedFidget", - "triggerRandomSwitch": "", - "triggerTimeMax": 45, - "triggerTimeMin": 10 - }, - "id": "seatedIdle", - "type": "randomSwitchStateMachine" - } - ], - "data": { - "alpha": 1, - "alphaVar": "talkOverlayAlpha", - "boneSet": "upperBody" - }, - "id": "seatedTalkOverlay", - "type": "overlay" - }, - { - "children": [ - { - "children": [ - ], - "data": { - "endFrame": 44, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_agree_headnod.fbx" - }, - "id": "seatedReactionPositiveHeadNod", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 78, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_agree_headnodyes.fbx" - }, - "id": "seatedReactionPositiveHeadNodYes", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 65, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_agree_longheadnod.fbx" - }, - "id": "seatedReactionPositiveLongHeadNod", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 78, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_agree_cheer.fbx" - }, - "id": "seatedReactionPositiveCheer", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 64, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_agree_acknowledge.fbx" - }, - "id": "seatedReactionPositiveAcknowledge", - "type": "clip" - } - ], - "data": { - "currentState": "seatedReactionPositiveHeadNod", - "endFrame": 30, - "loopFlag": false, - "randomSwitchTimeMax": 12, - "randomSwitchTimeMin": 7, - "startFrame": 0, - "states": [ - { - "id": "seatedReactionPositiveHeadNod", - "interpDuration": 1, - "interpTarget": 1, - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "id": "seatedReactionPositiveHeadNodYes", - "interpDuration": 1, - "interpTarget": 1, - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "id": "seatedReactionPositiveLongHeadNod", - "interpDuration": 1, - "interpTarget": 1, - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "id": "seatedReactionPositiveCheer", - "interpDuration": 1, - "interpTarget": 1, - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "id": "seatedReactionPositiveAcknowledge", - "interpDuration": 1, - "interpTarget": 1, - "priority": 1, - "resume": false, - "transitions": [ - ] - } - ], - "timeScale": 1, - "triggerRandomSwitch": "", - "url": "qrc:///avatar/animations/sitting_idle.fbx" - }, - "id": "seatedReactionPositive", - "type": "randomSwitchStateMachine" - }, - { - "children": [ - { - "children": [ - ], - "data": { - "endFrame": 64, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_disagree_headshake.fbx" - }, - "id": "seatedReactionNegativeDisagreeHeadshake", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 99, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_disagree_drophead.fbx" - }, - "id": "seatedReactionNegativeDisagreeDropHead", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 124, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_disagree_disbelief.fbx" - }, - "id": "seatedReactionNegativeDisagreeDisbelief", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 70, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_disagree_dismiss.fbx" - }, - "id": "seatedReactionNegativeDisagreeDismiss", - "type": "clip" - } - ], - "data": { - "currentState": "seatedReactionNegativeDisagreeHeadshake", - "endFrame": 30, - "loopFlag": false, - "randomSwitchTimeMax": 10, - "randomSwitchTimeMin": 1, - "startFrame": 0, - "states": [ - { - "easingType": "easeInOutQuad", - "id": "seatedReactionNegativeDisagreeHeadshake", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionNegativeDisagreeDropHead", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionNegativeDisagreeDisbelief", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionNegativeDisagreeDismiss", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - ] - } - ], - "timeScale": 1, - "triggerRandomSwitch": "", - "url": "qrc:///avatar/animations/sitting_idle.fbx" - }, - "id": "seatedReactionNegative", - "type": "randomSwitchStateMachine" - }, - { - "children": [ - { - "children": [ - ], - "data": { - "endFrame": 32, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" - }, - "id": "seatedReactionRaiseHandIntro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 345, - "loopFlag": true, - "startFrame": 32, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" - }, - "id": "seatedReactionRaiseHandLoop", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 400, - "loopFlag": false, - "startFrame": 345, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand_all.fbx" - }, - "id": "seatedReactionRaiseHandOutro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 18, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand02_all.fbx" - }, - "id": "seatedReactionRaiseHand02Intro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 378, - "loopFlag": true, - "startFrame": 18, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand02_all.fbx" - }, - "id": "seatedReactionRaiseHand02Loop", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 435, - "loopFlag": false, - "startFrame": 378, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand02_all.fbx" - }, - "id": "seatedReactionRaiseHand02Outro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 15, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand03_all.fbx" - }, - "id": "seatedReactionRaiseHand03Intro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 233, - "loopFlag": true, - "mirrorFlag": false, - "startFrame": 15, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand03_all.fbx" - }, - "id": "seatedReactionRaiseHand03Loop", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 296, - "loopFlag": false, - "mirrorFlag": false, - "startFrame": 233, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_raisehand03_all.fbx" - }, - "id": "seatedReactionRaiseHand03Outro", - "type": "clip" - } - ], - "data": { - "currentState": "seatedReactionRaiseHandIntro", - "randomSwitchTimeMax": 10, - "randomSwitchTimeMin": 1, - "states": [ - { - "easingType": "easeInOutQuad", - "id": "seatedReactionRaiseHandIntro", - "interpDuration": 8, - "interpTarget": 9, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHandLoop", - "var": "seatedReactionRaiseHandIntroOnDone" - } - ] - }, - { - "id": "seatedReactionRaiseHandLoop", - "interpDuration": 1, - "interpTarget": 1, - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHandOutro", - "var": "reactionRaiseHandDisabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionRaiseHandOutro", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHandLoop", - "var": "reactionRaiseHandEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionRaiseHand02Intro", - "interpDuration": 8, - "interpTarget": 8, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHand02Loop", - "var": "seatedReactionRaiseHand02IntroOnDone" - } - ] - }, - { - "id": "seatedReactionRaiseHand02Loop", - "interpDuration": 1, - "interpTarget": 1, - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHand02Outro", - "var": "reactionRaiseHandDisabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionRaiseHand02Outro", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHand02Loop", - "var": "reactionRaiseHandEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionRaiseHand03Intro", - "interpDuration": 8, - "interpTarget": 8, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHand03Loop", - "var": "seatedReactionRaiseHand03IntroOnDone" - } - ] - }, - { - "id": "seatedReactionRaiseHand03Loop", - "interpDuration": 1, - "interpTarget": 1, - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHand03Outro", - "var": "reactionRaiseHandDisabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionRaiseHand03Outro", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionRaiseHand03Loop", - "var": "reactionRaiseHandEnabled" - } - ] - } - ], - "triggerRandomSwitch": "" - }, - "id": "seatedReactionRaiseHand", - "type": "randomSwitchStateMachine" - }, - { - "children": [ - { - "children": [ - ], - "data": { - "endFrame": 12, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" - }, - "id": "seatedReactionApplaudIntro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 76, - "loopFlag": true, - "startFrame": 12, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" - }, - "id": "seatedReactionApplaudLoop", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 99, - "loopFlag": false, - "startFrame": 76, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap_all.fbx" - }, - "id": "seatedReactionApplaudOutro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 12, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap02_all.fbx" - }, - "id": "seatedReactionApplaud02Intro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 112, - "loopFlag": true, - "startFrame": 12, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap02_all.fbx" - }, - "id": "seatedReactionApplaud02Loop", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 132, - "loopFlag": false, - "startFrame": 112, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap02_all.fbx" - }, - "id": "seatedReactionApplaud02Outro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 17, - "loopFlag": false, - "startFrame": 0, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap03_all.fbx" - }, - "id": "seatedReactionApplaud03Intro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 111, - "loopFlag": true, - "startFrame": 17, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap03_all.fbx" - }, - "id": "seatedReactionApplaud03Loop", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 136, - "loopFlag": false, - "startFrame": 111, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_clap03_all.fbx" - }, - "id": "seatedReactionApplaud03Outro", - "type": "clip" - } - ], - "data": { - "currentState": "seatedReactionApplaudIntro", - "randomSwitchTimeMax": 10, - "randomSwitchTimeMin": 1, - "states": [ - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaudIntro", - "interpDuration": 8, - "interpTarget": 8, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaudLoop", - "var": "seatedReactionApplaudIntroOnDone" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaudLoop", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaudOutro", - "var": "reactionApplaudDisabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaudOutro", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaudLoop", - "var": "reactionApplaudEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaud02Intro", - "interpDuration": 8, - "interpTarget": 8, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaud02Loop", - "var": "seatedReactionApplaud02IntroOnDone" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaud02Loop", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaud02Outro", - "var": "reactionApplaudDisabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaud02Outro", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaud02Loop", - "var": "reactionApplaudEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaud03Intro", - "interpDuration": 8, - "interpTarget": 8, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaud03Loop", - "var": "seatedReactionApplaud03IntroOnDone" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaud03Loop", - "interpDuration": 1, - "interpTarget": 1, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaud03Outro", - "var": "reactionApplaudDisabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaud03Outro", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionApplaud03Loop", - "var": "reactionApplaudEnabled" - } - ] - } - ], - "triggerRandomSwitch": "" - }, - "id": "seatedReactionApplaud", - "type": "randomSwitchStateMachine" - }, - { - "children": [ - { - "children": [ - { - "children": [ - { - "children": [ - ], - "data": { - "endFrame": 21, - "loopFlag": false, - "startFrame": 1, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" - }, - "id": "seatedReactionPointIntro", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "endFrame": 100, + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 11, "loopFlag": true, - "startFrame": 21, + "startFrame": 11, "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" }, - "id": "seatedReactionPointLoop", + "id": "seatedPointLeft", "type": "clip" }, { "children": [ ], "data": { - "endFrame": 134, - "loopFlag": false, - "mirrorFlag": false, - "startFrame": 100, + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 30, + "loopFlag": true, + "startFrame": 30, "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_all.fbx" + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" }, - "id": "seatedReactionPointOutro", + "id": "seatedPointRight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 50, + "loopFlag": true, + "startFrame": 50, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" + }, + "id": "seatedPointUp", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 70, + "loopFlag": true, + "startFrame": 70, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" + }, + "id": "seatedPointDown", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 90, + "loopFlag": true, + "startFrame": 90, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" + }, + "id": "seatedPointUpLeft", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 110, + "loopFlag": true, + "startFrame": 110, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" + }, + "id": "seatedPointUpRight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 130, + "loopFlag": true, + "startFrame": 130, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" + }, + "id": "seatedPointDownLeft", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 150, + "loopFlag": true, + "startFrame": 150, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" + }, + "id": "seatedPointDownRight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 3, + "loopFlag": true, + "startFrame": 3, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" + }, + "id": "seatedPointCenter", "type": "clip" } ], "data": { - "currentState": "seatedReactionPointIntro", - "randomSwitchTimeMax": 10, - "randomSwitchTimeMin": 1, - "states": [ - { - "easingType": "easeInOutQuad", - "id": "seatedReactionPointIntro", - "interpDuration": 18, - "interpTarget": 18, - "interpType": "evaluateBoth", - "priority": 1, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionPointLoop", - "var": "seatedReactionPointIntroOnDone" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionPointLoop", - "interpDuration": 18, - "interpTarget": 18, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionPointOutro", - "var": "reactionPointDisabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionPointOutro", - "interpDuration": 18, - "interpTarget": 18, - "interpType": "evaluateBoth", - "priority": 0, - "resume": false, - "transitions": [ - { - "randomSwitchState": "seatedReactionPointLoop", - "var": "reactionPointEnabled" - } - ] - } + "alpha": [ + 0, + 0, + 0 ], - "triggerRandomSwitch": "" + "alphaVar": "pointAroundAlpha", + "centerId": "seatedPointCenter", + "downId": "seatedPointDown", + "downLeftId": "seatedPointDownLeft", + "downRightId": "seatedPointDownRight", + "leftId": "seatedPointLeft", + "rightId": "seatedPointRight", + "upId": "seatedPointUp", + "upLeftId": "seatedPointUpLeft", + "upRightId": "seatedPointUpRight" }, - "id": "seatedReactionPoint", - "type": "randomSwitchStateMachine" + "id": "seatedPointAround", + "type": "blendDirectional" } ], "data": { "alpha": 0, - "alphaVar": "seatedPointBlendAlpha", + "alphaVar": "pointBlendAlpha", "blendType": "addAbsolute" }, - "id": "seatedReactionPointBase", + "id": "seatedReactionPoint", "type": "blendLinear" - }, - { - "children": [ - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 11, - "loopFlag": true, - "startFrame": 11, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointLeft", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 30, - "loopFlag": true, - "startFrame": 30, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointRight", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 50, - "loopFlag": true, - "startFrame": 50, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointUp", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 70, - "loopFlag": true, - "startFrame": 70, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointDown", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 90, - "loopFlag": true, - "startFrame": 90, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointUpLeft", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 110, - "loopFlag": true, - "startFrame": 110, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointUpRight", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 130, - "loopFlag": true, - "startFrame": 130, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointDownLeft", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 150, - "loopFlag": true, - "startFrame": 150, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointDownRight", - "type": "clip" - }, - { - "children": [ - ], - "data": { - "baseFrame": 1, - "baseURL": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx", - "blendType": "addAbsolute", - "endFrame": 3, - "loopFlag": true, - "startFrame": 3, - "timeScale": 1, - "url": "qrc:///avatar/animations/sitting_emote_point_aimoffsets.fbx" - }, - "id": "seatedPointCenter", - "type": "clip" - } - ], - "data": { - "alpha": [ - 0, - 0, - 0 - ], - "alphaVar": "pointAroundAlpha", - "centerId": "seatedPointCenter", - "downId": "seatedPointDown", - "downLeftId": "seatedPointDownLeft", - "downRightId": "seatedPointDownRight", - "leftId": "seatedPointLeft", - "rightId": "seatedPointRight", - "upId": "seatedPointUp", - "upLeftId": "seatedPointUpLeft", - "upRightId": "seatedPointUpRight" - }, - "id": "seatedPointAround", - "type": "blendDirectional" } ], "data": { - "alpha": 0, - "alphaVar": "pointBlendAlpha", - "blendType": "addAbsolute" + "currentState": "seatedTalkOverlay", + "states": [ + { + "easingType": "easeInOutQuad", + "id": "seatedTalkOverlay", + "interpDuration": 25, + "interpTarget": 25, + "interpType": "evaluateBoth", + "transitions": [ + { + "state": "seatedReactionPositive", + "var": "reactionPositiveTrigger" + }, + { + "state": "seatedReactionNegative", + "var": "reactionNegativeTrigger" + }, + { + "state": "seatedReactionRaiseHand", + "var": "reactionRaiseHandEnabled" + }, + { + "state": "seatedReactionApplaud", + "var": "reactionApplaudEnabled" + }, + { + "state": "seatedReactionPoint", + "var": "reactionPointEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionPositive", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "transitions": [ + { + "state": "seatedTalkOverlay", + "var": "seatedReactionPositiveHeadNodOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionPositiveHeadNodYesOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionPositiveLongHeadNodOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionPositiveCheerOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionPositiveAcknowledgeOnDone" + }, + { + "state": "seatedReactionNegative", + "var": "reactionNegativeTrigger" + }, + { + "state": "seatedReactionRaiseHand", + "var": "reactionRaiseHandEnabled" + }, + { + "state": "seatedReactionApplaud", + "var": "reactionApplaudEnabled" + }, + { + "state": "seatedReactionPoint", + "var": "reactionPointEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionNegative", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "transitions": [ + { + "state": "seatedReactionPositive", + "var": "reactionPositiveTrigger" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionNegativeDisagreeHeadshakeOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionNegativeDisagreeDropHeadOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionNegativeDisagreeDisbeliefOnDone" + }, + { + "state": "seatedTalkOverlay", + "var": "seatedReactionNegativeDisagreeDismissOnDone" + }, + { + "state": "seatedReactionRaiseHand", + "var": "reactionRaiseHandEnabled" + }, + { + "state": "seatedReactionApplaud", + "var": "reactionApplaudEnabled" + }, + { + "state": "seatedReactionPoint", + "var": "reactionPointEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionRaiseHand", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "transitions": [ + { + "state": "seatedReactionNegative", + "var": "reactionNegativeTrigger" + }, + { + "state": "seatedReactionPositive", + "var": "reactionPositiveTrigger" + }, + { + "state": "seatedTalkOverlay", + "var": "reactionRaiseHandDisabled" + }, + { + "state": "seatedReactionApplaud", + "var": "reactionApplaudEnabled" + }, + { + "state": "seatedReactionPoint", + "var": "reactionPointEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionApplaud", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "transitions": [ + { + "state": "seatedReactionNegative", + "var": "reactionNegativeTrigger" + }, + { + "state": "seatedReactionPositive", + "var": "reactionPositiveTrigger" + }, + { + "state": "seatedReactionRaiseHand", + "var": "reactionRaiseHandEnabled" + }, + { + "state": "seatedTalkOverlay", + "var": "reactionApplaudDisabled" + }, + { + "state": "seatedReactionPoint", + "var": "reactionPointEnabled" + } + ] + }, + { + "easingType": "easeInOutQuad", + "id": "seatedReactionPoint", + "interpDuration": 12, + "interpTarget": 12, + "interpType": "evaluateBoth", + "transitions": [ + { + "state": "seatedReactionNegative", + "var": "reactionNegativeTrigger" + }, + { + "state": "seatedReactionPositive", + "var": "reactionPositiveTrigger" + }, + { + "state": "seatedReactionRaiseHand", + "var": "reactionRaiseHandEnabled" + }, + { + "state": "seatedReactionApplaud", + "var": "reactionApplaudEnabled" + }, + { + "state": "seatedTalkOverlay", + "var": "reactionPointDisabled" + } + ] + } + ] }, - "id": "seatedReactionPoint", - "type": "blendLinear" + "id": "seatedSM", + "type": "stateMachine" + }, + { + "children": [ + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 11, + "loopFlag": true, + "startFrame": 11, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookLeft", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 30, + "loopFlag": true, + "startFrame": 30, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookRight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 50, + "loopFlag": true, + "startFrame": 50, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookUp", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 70, + "loopFlag": true, + "startFrame": 70, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookDown", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 97, + "loopFlag": true, + "startFrame": 97, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookUpLeft", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 110, + "loopFlag": true, + "startFrame": 110, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookUpRight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 130, + "loopFlag": true, + "startFrame": 130, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookDownLeft", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 150, + "loopFlag": true, + "startFrame": 150, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookDownRight", + "type": "clip" + }, + { + "children": [ + ], + "data": { + "baseFrame": 1, + "baseURL": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx", + "blendType": "addAbsolute", + "endFrame": 3, + "loopFlag": true, + "startFrame": 3, + "timeScale": 1, + "url": "qrc:///avatar/animations/sitting_idle_aimoffsets.fbx" + }, + "id": "seatedLookCenter", + "type": "clip" + } + ], + "data": { + "alpha": [ + 0, + 0, + 0 + ], + "alphaVar": "lookAroundAlpha", + "centerId": "seatedLookCenter", + "downId": "seatedLookDown", + "downLeftId": "seatedLookDownLeft", + "downRightId": "seatedLookDownRight", + "leftId": "seatedLookLeft", + "rightId": "seatedLookRight", + "upId": "seatedLookUp", + "upLeftId": "seatedLookUpLeft", + "upRightId": "seatedLookUpRight" + }, + "id": "seatedLookAroundBlend", + "type": "blendDirectional" } ], "data": { - "currentState": "seatedTalkOverlay", - "states": [ - { - "easingType": "easeInOutQuad", - "id": "seatedTalkOverlay", - "interpDuration": 25, - "interpTarget": 25, - "interpType": "evaluateBoth", - "transitions": [ - { - "state": "seatedReactionPositive", - "var": "reactionPositiveTrigger" - }, - { - "state": "seatedReactionNegative", - "var": "reactionNegativeTrigger" - }, - { - "state": "seatedReactionRaiseHand", - "var": "reactionRaiseHandEnabled" - }, - { - "state": "seatedReactionApplaud", - "var": "reactionApplaudEnabled" - }, - { - "state": "seatedReactionPoint", - "var": "reactionPointEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionPositive", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "transitions": [ - { - "state": "seatedTalkOverlay", - "var": "seatedReactionPositiveHeadNodOnDone" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionPositiveHeadNodYesOnDone" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionPositiveLongHeadNodOnDone" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionPositiveCheerOnDone" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionPositiveAcknowledgeOnDone" - }, - { - "state": "seatedReactionNegative", - "var": "reactionNegativeTrigger" - }, - { - "state": "seatedReactionRaiseHand", - "var": "reactionRaiseHandEnabled" - }, - { - "state": "seatedReactionApplaud", - "var": "reactionApplaudEnabled" - }, - { - "state": "seatedReactionPoint", - "var": "reactionPointEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionNegative", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "transitions": [ - { - "state": "seatedReactionPositive", - "var": "reactionPositiveTrigger" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionNegativeDisagreeHeadshakeOnDone" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionNegativeDisagreeDropHeadOnDone" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionNegativeDisagreeDisbeliefOnDone" - }, - { - "state": "seatedTalkOverlay", - "var": "seatedReactionNegativeDisagreeDismissOnDone" - }, - { - "state": "seatedReactionRaiseHand", - "var": "reactionRaiseHandEnabled" - }, - { - "state": "seatedReactionApplaud", - "var": "reactionApplaudEnabled" - }, - { - "state": "seatedReactionPoint", - "var": "reactionPointEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionRaiseHand", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "transitions": [ - { - "state": "seatedReactionNegative", - "var": "reactionNegativeTrigger" - }, - { - "state": "seatedReactionPositive", - "var": "reactionPositiveTrigger" - }, - { - "state": "seatedTalkOverlay", - "var": "reactionRaiseHandDisabled" - }, - { - "state": "seatedReactionApplaud", - "var": "reactionApplaudEnabled" - }, - { - "state": "seatedReactionPoint", - "var": "reactionPointEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionApplaud", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "transitions": [ - { - "state": "seatedReactionNegative", - "var": "reactionNegativeTrigger" - }, - { - "state": "seatedReactionPositive", - "var": "reactionPositiveTrigger" - }, - { - "state": "seatedReactionRaiseHand", - "var": "reactionRaiseHandEnabled" - }, - { - "state": "seatedTalkOverlay", - "var": "reactionApplaudDisabled" - }, - { - "state": "seatedReactionPoint", - "var": "reactionPointEnabled" - } - ] - }, - { - "easingType": "easeInOutQuad", - "id": "seatedReactionPoint", - "interpDuration": 12, - "interpTarget": 12, - "interpType": "evaluateBoth", - "transitions": [ - { - "state": "seatedReactionNegative", - "var": "reactionNegativeTrigger" - }, - { - "state": "seatedReactionPositive", - "var": "reactionPositiveTrigger" - }, - { - "state": "seatedReactionRaiseHand", - "var": "reactionRaiseHandEnabled" - }, - { - "state": "seatedReactionApplaud", - "var": "reactionApplaudEnabled" - }, - { - "state": "seatedTalkOverlay", - "var": "reactionPointDisabled" - } - ] - } - ] + "alpha": 0, + "alphaVar": "seatedLookBlendAlpha", + "blendType": "addAbsolute" }, "id": "seated", - "type": "stateMachine" + "type": "blendLinear" }, { "children": [ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ed314c103e..a1c6efa32d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -106,7 +106,7 @@ #include #include #include -#include +#include #include #include #include @@ -159,7 +159,8 @@ #include #include #include -#include +#include +#include #include "recording/ClipCache.h" #include "AudioClient.h" @@ -2090,7 +2091,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo EntityTreeRenderer::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { auto avatarManager = DependencyManager::get(); - auto avatar = avatarManager->getAvatarBySessionID(avatarID); + auto avatar = static_pointer_cast(avatarManager->getAvatarBySessionID(avatarID)); if (avatar) { avatar->addMaterial(material, parentMaterialName); return true; @@ -2099,13 +2100,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); EntityTreeRenderer::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { auto avatarManager = DependencyManager::get(); - auto avatar = avatarManager->getAvatarBySessionID(avatarID); + auto avatar = static_pointer_cast(avatarManager->getAvatarBySessionID(avatarID)); if (avatar) { avatar->removeMaterial(material, parentMaterialName); return true; } return false; }); + Procedural::opaqueStencil = [](gpu::StatePointer state) { PrepareStencil::testMaskDrawShape(*state); }; + Procedural::transparentStencil = [](gpu::StatePointer state) { PrepareStencil::testMask(*state); }; EntityTree::setGetEntityObjectOperator([this](const QUuid& id) -> QObject* { auto entities = getEntities(); @@ -7084,10 +7087,6 @@ void Application::clearDomainOctreeDetails(bool clearAll) { // reset the model renderer clearAll ? getEntities()->clear() : getEntities()->clearDomainAndNonOwnedEntities(); - auto skyStage = DependencyManager::get()->getSkyStage(); - - skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT); - DependencyManager::get()->clearUnusedResources(); DependencyManager::get()->clearUnusedResources(); DependencyManager::get()->clearUnusedResources(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index fe269a6a64..508c44fbd1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -53,6 +53,7 @@ #include "SpeechRecognizer.h" #endif +#include "MeshPartPayload.h" #include "scripting/RenderScriptingInterface.h" extern bool DEV_DECIMATE_TEXTURES; @@ -470,6 +471,11 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ComputeBlendshapes, 0, true, DependencyManager::get().data(), SLOT(setComputeBlendshapes(bool))); + action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false); + connect(action, &QAction::triggered, [action] { + MeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); + }); + { auto drawStatusConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DrawStatus"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::HighlightTransitions, 0, false, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 4a2a97b168..ea118ec5dd 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -228,6 +228,7 @@ namespace MenuOption { const QString ForceCoarsePicking = "Force Coarse Picking"; const QString ComputeBlendshapes = "Compute Blendshapes"; const QString HighlightTransitions = "Highlight Transitions"; + const QString MaterialProceduralShaders = "Enable Procedural Materials"; } #endif // hifi_Menu_h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ccf3b474b1..48f218b817 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -100,7 +100,7 @@ static const QString USER_RECENTER_MODEL_DISABLE_HMD_LEAN = QStringLiteral("Disa const QString HEAD_BLEND_DIRECTIONAL_ALPHA_NAME = "lookAroundAlpha"; const QString HEAD_BLEND_LINEAR_ALPHA_NAME = "lookBlendAlpha"; -const float HEAD_ALPHA_BLENDING = 1.0f; +const QString SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME = "seatedLookBlendAlpha"; const QString POINT_REACTION_NAME = "point"; const QString POINT_BLEND_DIRECTIONAL_ALPHA_NAME = "pointAroundAlpha"; @@ -6672,8 +6672,17 @@ glm::vec3 MyAvatar::aimToBlendValues(const glm::vec3& aimVector, const glm::quat void MyAvatar::resetHeadLookAt() { if (_skeletonModel->isLoaded()) { - _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(), - HEAD_BLEND_LINEAR_ALPHA_NAME, HEAD_ALPHA_BLENDING); + if (isSeated()) { + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(), + HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f); + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(), + SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f); + } else { + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(), + HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f); + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, glm::vec3(), + SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f); + } } } @@ -6686,13 +6695,22 @@ void MyAvatar::resetLookAtRotation(const glm::vec3& avatarPosition, const glm::q resetHeadLookAt(); } -void MyAvatar::updateHeadLookAt(float deltaTime) { +void MyAvatar::updateHeadLookAt(float deltaTime) { if (_skeletonModel->isLoaded()) { glm::vec3 lookAtTarget = _scriptControlsHeadLookAt ? _lookAtScriptTarget : _lookAtCameraTarget; glm::vec3 aimVector = lookAtTarget - getDefaultEyePosition(); glm::vec3 lookAtBlend = MyAvatar::aimToBlendValues(aimVector, getWorldOrientation()); - _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend, - HEAD_BLEND_LINEAR_ALPHA_NAME, HEAD_ALPHA_BLENDING); + if (isSeated()) { + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend, + HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f); + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend, + SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f); + } else { + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend, + HEAD_BLEND_LINEAR_ALPHA_NAME, 1.0f); + _skeletonModel->getRig().setDirectionalBlending(HEAD_BLEND_DIRECTIONAL_ALPHA_NAME, lookAtBlend, + SEATED_HEAD_BLEND_LINEAR_ALPHA_NAME, 0.0f); + } if (_scriptControlsHeadLookAt) { _scriptHeadControlTimer += deltaTime; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 9e98b84edc..7e11406808 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -102,6 +102,16 @@ void setupPreferences() { preference->setItems(refreshRateProfiles); preferences->addPreference(preference); + + auto getterMaterialProceduralShaders = []() -> bool { + auto menu = Menu::getInstance(); + return menu->isOptionChecked(MenuOption::MaterialProceduralShaders); + }; + auto setterMaterialProceduralShaders = [](bool value) { + auto menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::MaterialProceduralShaders, value); + }; + preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Enable Procedural Materials", getterMaterialProceduralShaders, setterMaterialProceduralShaders)); } { // Expose the Viewport Resolution Scale diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index d8741e4aa7..d6faea4396 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1187,12 +1187,12 @@ void AudioClient::processWebrtcFarEnd(const int16_t* samples, int numFrames, int const webrtc::StreamConfig streamConfig = webrtc::StreamConfig(sampleRate, numChannels); const int numChunk = (int)streamConfig.num_frames(); - if (sampleRate > WEBRTC_SAMPLE_RATE_MAX) { - qCWarning(audioclient) << "WebRTC does not support" << sampleRate << "output sample rate."; - return; - } - if (numChannels > WEBRTC_CHANNELS_MAX) { - qCWarning(audioclient) << "WebRTC does not support" << numChannels << "output channels."; + static int32_t lastWarningHash = 0; + if (sampleRate > WEBRTC_SAMPLE_RATE_MAX || numChannels > WEBRTC_CHANNELS_MAX) { + if (lastWarningHash != ((sampleRate << 8) | numChannels)) { + lastWarningHash = ((sampleRate << 8) | numChannels); + qCWarning(audioclient) << "AEC not unsupported for output format: sampleRate =" << sampleRate << "numChannels =" << numChannels; + } return; } @@ -1227,18 +1227,14 @@ void AudioClient::processWebrtcFarEnd(const int16_t* samples, int numFrames, int void AudioClient::processWebrtcNearEnd(int16_t* samples, int numFrames, int numChannels, int sampleRate) { const webrtc::StreamConfig streamConfig = webrtc::StreamConfig(sampleRate, numChannels); - const int numChunk = (int)streamConfig.num_frames(); + assert(numFrames == (int)streamConfig.num_frames()); // WebRTC requires exactly 10ms of input - if (sampleRate > WEBRTC_SAMPLE_RATE_MAX) { - qCWarning(audioclient) << "WebRTC does not support" << sampleRate << "input sample rate."; - return; - } - if (numChannels > WEBRTC_CHANNELS_MAX) { - qCWarning(audioclient) << "WebRTC does not support" << numChannels << "input channels."; - return; - } - if (numFrames != numChunk) { - qCWarning(audioclient) << "WebRTC requires exactly 10ms of input."; + static int32_t lastWarningHash = 0; + if (sampleRate > WEBRTC_SAMPLE_RATE_MAX || numChannels > WEBRTC_CHANNELS_MAX) { + if (lastWarningHash != ((sampleRate << 8) | numChannels)) { + lastWarningHash = ((sampleRate << 8) | numChannels); + qCWarning(audioclient) << "AEC not unsupported for input format: sampleRate =" << sampleRate << "numChannels =" << numChannels; + } return; } diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index 7929be8b04..deba2913c1 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME avatars-renderer) setup_hifi_library(Network Script) -link_hifi_libraries(shared shaders gpu graphics animation material-networking model-networking script-engine render render-utils image entities-renderer) +link_hifi_libraries(shared shaders gpu graphics animation material-networking model-networking script-engine render render-utils image entities-renderer physics) include_hifi_library_headers(avatars) include_hifi_library_headers(networking) include_hifi_library_headers(hfm) @@ -8,8 +8,6 @@ include_hifi_library_headers(fbx) include_hifi_library_headers(recording) include_hifi_library_headers(ktx) include_hifi_library_headers(procedural) -include_hifi_library_headers(physics) -include_hifi_library_headers(entities-renderer) include_hifi_library_headers(audio) include_hifi_library_headers(entities) include_hifi_library_headers(octree) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 610f34ed45..031b2f1309 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -547,8 +547,8 @@ public: virtual void setEnableMeshVisible(bool isEnabled); virtual bool getEnableMeshVisible() const; - void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override; - void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override; + void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); + void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); virtual scriptable::ScriptableModelBase getScriptableModel() override; diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index 13fda28f40..fc6d15cced 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -1,4 +1,3 @@ set(TARGET_NAME avatars) setup_hifi_library(Network Script) -include_hifi_library_headers(gpu) -link_hifi_libraries(shared networking graphics) +link_hifi_libraries(shared networking) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 16fe4d82d4..e8aee1f3d2 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -55,8 +55,6 @@ #include "HeadData.h" #include "PathUtils.h" -#include - using AvatarSharedPointer = std::shared_ptr; using AvatarWeakPointer = std::weak_ptr; using AvatarHash = QHash; @@ -1493,8 +1491,6 @@ public: bool getIsReplicated() const { return _isReplicated; } - virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {} - virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {} void setReplicaIndex(int replicaIndex) { _replicaIndex = replicaIndex; } int getReplicaIndex() { return _replicaIndex; } diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 17a3d28eb0..c474353451 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -44,6 +44,7 @@ const quint64 MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS = USECS_PER_SECOND / CLIENT_ * @namespace AvatarList * * @hifi-assignment-client + * @hifi-server-entity */ class AvatarReplicas { diff --git a/libraries/baking/CMakeLists.txt b/libraries/baking/CMakeLists.txt index 73618427f6..4350f386ab 100644 --- a/libraries/baking/CMakeLists.txt +++ b/libraries/baking/CMakeLists.txt @@ -1,6 +1,7 @@ set(TARGET_NAME baking) setup_hifi_library(Concurrent) -link_hifi_libraries(shared shaders graphics networking material-networking graphics-scripting ktx image fbx model-baker task) +link_hifi_libraries(shared shaders graphics networking procedural graphics-scripting ktx image fbx model-baker task) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) +include_hifi_library_headers(material-networking) \ No newline at end of file diff --git a/libraries/baking/src/MaterialBaker.h b/libraries/baking/src/MaterialBaker.h index bb47941af6..68efcfbd7e 100644 --- a/libraries/baking/src/MaterialBaker.h +++ b/libraries/baking/src/MaterialBaker.h @@ -17,7 +17,7 @@ #include "TextureBaker.h" #include "baking/TextureFileNamer.h" -#include +#include static const QString BAKED_MATERIAL_EXTENSION = ".baked.json"; diff --git a/libraries/baking/src/TextureBaker.h b/libraries/baking/src/TextureBaker.h index 5fda05e9b4..5c6c85ea16 100644 --- a/libraries/baking/src/TextureBaker.h +++ b/libraries/baking/src/TextureBaker.h @@ -22,7 +22,7 @@ #include "Baker.h" -#include +#include extern const QString BAKED_TEXTURE_KTX_EXT; extern const QString BAKED_META_TEXTURE_SUFFIX; diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index ad6503b22d..bfe88f2eb8 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -11,6 +11,7 @@ include_hifi_library_headers(fbx) include_hifi_library_headers(image) include_hifi_library_headers(ktx) include_hifi_library_headers(render) +include_hifi_library_headers(procedural) target_opengl() diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index eae0561343..a013ff75b7 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -11,6 +11,8 @@ #include "RenderPipelines.h" #include "GeometryCache.h" +#include + using namespace render; using namespace render::entities; @@ -227,31 +229,31 @@ ItemKey MaterialEntityRenderer::getKey() { } ShapeKey MaterialEntityRenderer::getShapeKey() { + ShapeKey::Builder builder; graphics::MaterialKey drawMaterialKey; const auto drawMaterial = getMaterial(); if (drawMaterial) { drawMaterialKey = drawMaterial->getKey(); } - bool isTranslucent = drawMaterialKey.isTranslucent(); - bool hasTangents = drawMaterialKey.isNormalMap(); - bool hasLightmap = drawMaterialKey.isLightMap(); - bool isUnlit = drawMaterialKey.isUnlit(); - - ShapeKey::Builder builder; - builder.withMaterial(); - - if (isTranslucent) { + if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } - if (hasTangents) { - builder.withTangents(); - } - if (hasLightmap) { - builder.withLightMap(); - } - if (isUnlit) { - builder.withUnlit(); + + if (drawMaterial && drawMaterial->isProcedural() && drawMaterial->isReady()) { + builder.withOwnPipeline(); + } else { + builder.withMaterial(); + + if (drawMaterialKey.isNormalMap()) { + builder.withTangents(); + } + if (drawMaterialKey.isLightMap()) { + builder.withLightMap(); + } + if (drawMaterialKey.isUnlit()) { + builder.withUnlit(); + } } if (_primitiveMode == PrimitiveMode::LINES) { @@ -277,6 +279,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { Transform renderTransform; graphics::MaterialPointer drawMaterial; + bool proceduralRender = false; Transform textureTransform; withReadLock([&] { renderTransform = _renderTransform; @@ -284,6 +287,10 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0)); textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot))); textureTransform.setScale(glm::vec3(_materialMappingScale, 1)); + + if (drawMaterial && drawMaterial->isProcedural() && drawMaterial->isReady()) { + proceduralRender = true; + } }); if (!drawMaterial) { return; @@ -291,14 +298,27 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { batch.setModelTransform(renderTransform); - drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); - // bind the material - if (RenderPipelines::bindMaterial(drawMaterial, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; - } + if (!proceduralRender) { + drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); + // bind the material + if (RenderPipelines::bindMaterial(drawMaterial, batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; + } - // Draw! - DependencyManager::get()->renderSphere(batch); + // Draw! + DependencyManager::get()->renderSphere(batch); + } else { + auto proceduralDrawMaterial = std::static_pointer_cast(drawMaterial); + glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity()); + outColor = proceduralDrawMaterial->getColor(outColor); + proceduralDrawMaterial->prepare(batch, renderTransform.getTranslation(), renderTransform.getScale(), + renderTransform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { + DependencyManager::get()->renderWireSphere(batch, outColor); + } else { + DependencyManager::get()->renderSphere(batch, outColor); + } + } args->_details._trianglesRendered += (int)DependencyManager::get()->getSphereTriangleCount(); } diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index 0c347155e0..ff7367a44e 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -13,7 +13,7 @@ #include -#include +#include class NetworkMaterial; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d7da3879f6..287f022007 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1316,7 +1316,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // Check for addition if (_hasModel && !model) { - model = std::make_shared(nullptr, entity.get()); + model = std::make_shared(nullptr, entity.get(), _created); connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate); connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) { setKey(didVisualGeometryRequestSucceed); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 4f1ebaecb9..88cc78b6b6 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -12,17 +12,11 @@ #include #include -#include #include #include -#include #include "RenderPipelines.h" -//#define SHAPE_ENTITY_USE_FADE_EFFECT -#ifdef SHAPE_ENTITY_USE_FADE_EFFECT -#include -#endif using namespace render; using namespace render::entities; @@ -31,25 +25,20 @@ using namespace render::entities; static const float SPHERE_ENTITY_SCALE = 0.5f; ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { - _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural); - // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering - _procedural._opaqueFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural); - _procedural._transparentFragmentSource = gpu::Shader::Source::get(shader::render_utils::fragment::simple_procedural_translucent); - - // TODO: move into Procedural.cpp - PrepareStencil::testMaskDrawShape(*_procedural._opaqueState); - PrepareStencil::testMask(*_procedural._transparentState); - addMaterial(graphics::MaterialLayer(_material, 0), "0"); } bool ShapeEntityRenderer::needsRenderUpdate() const { if (resultWithReadLock([&] { - if (_procedural.isEnabled() && _procedural.isFading()) { - return true; + auto mat = _materials.find("0"); + if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && + mat->second.top().material->isEnabled()) { + auto procedural = std::static_pointer_cast(mat->second.top().material); + if (procedural->isFading()) { + return true; + } } - auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.shouldUpdate()) { return true; } @@ -67,7 +56,7 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } - if (_lastUserData != entity->getUserData()) { + if (_proceduralData != entity->getUserData()) { return true; } @@ -76,12 +65,6 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { withWriteLock([&] { - auto userData = entity->getUserData(); - if (_lastUserData != userData) { - _lastUserData = userData; - _procedural.setProceduralData(ProceduralData::parse(_lastUserData)); - } - _shape = entity->getShape(); _pulseProperties = entity->getPulseProperties(); }); @@ -106,25 +89,45 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { withReadLock([&] { - if (_procedural.isEnabled() && _procedural.isFading()) { - float isFading = Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; - _procedural.setIsFading(isFading); + auto mat = _materials.find("0"); + if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && mat->second.top().material->isEnabled()) { + auto procedural = std::static_pointer_cast(mat->second.top().material); + if (procedural->isFading()) { + procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f); + } } }); - glm::vec3 color = toGlm(entity->getColor()); - float alpha = entity->getAlpha(); - if (_color != color || _alpha != alpha) { - _color = color; - _alpha = alpha; - _material->setAlbedo(color); - _material->setOpacity(_alpha); - - auto materials = _materials.find("0"); - if (materials != _materials.end()) { - materials->second.setNeedsUpdate(true); + withWriteLock([&] { + bool materialChanged = false; + glm::vec3 color = toGlm(entity->getColor()); + if (_color != color) { + _color = color; + _material->setAlbedo(color); + materialChanged = true; } - } + + float alpha = entity->getAlpha(); + if (_alpha != alpha) { + _alpha = alpha; + _material->setOpacity(alpha); + materialChanged = true; + } + + auto userData = entity->getUserData(); + if (_proceduralData != userData) { + _proceduralData = userData; + _material->setProceduralData(_proceduralData); + materialChanged = true; + } + + if (materialChanged) { + auto materials = _materials.find("0"); + if (materials != _materials.end()) { + materials->second.setNeedsUpdate(true); + } + } + }); } bool ShapeEntityRenderer::isTransparent() const { @@ -132,12 +135,15 @@ bool ShapeEntityRenderer::isTransparent() const { return true; } - if (_procedural.isEnabled() && _procedural.isFading()) { - return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; - } - auto mat = _materials.find("0"); - if (mat != _materials.end()) { + if (mat != _materials.end() && mat->second.top().material) { + if (mat->second.top().material->isProcedural() && mat->second.top().material->isEnabled()) { + auto procedural = std::static_pointer_cast(mat->second.top().material); + if (procedural->isFading()) { + return true; + } + } + if (mat->second.getMaterialKey().isTranslucent()) { return true; } @@ -146,80 +152,59 @@ bool ShapeEntityRenderer::isTransparent() const { return Parent::isTransparent(); } -bool ShapeEntityRenderer::useMaterialPipeline(const graphics::MultiMaterial& materials) const { - bool proceduralReady = resultWithReadLock([&] { - return _procedural.isReady(); - }); - if (proceduralReady) { - return false; +ShapeEntityRenderer::Pipeline ShapeEntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) const { + if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) { + return Pipeline::PROCEDURAL; } graphics::MaterialKey drawMaterialKey = materials.getMaterialKey(); if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) { - return true; + return Pipeline::MATERIAL; } // If the material is using any map, we need to use a material ShapeKey for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) { if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) { - return true; + return Pipeline::MATERIAL; } } - return false; + return Pipeline::SIMPLE; } ShapeKey ShapeEntityRenderer::getShapeKey() { + ShapeKey::Builder builder; auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.shouldUpdate()) { RenderPipelines::updateMultiMaterial(mat->second); } - if (mat != _materials.end() && useMaterialPipeline(mat->second)) { - graphics::MaterialKey drawMaterialKey = mat->second.getMaterialKey(); + if (isTransparent()) { + builder.withTranslucent(); + } - bool isTranslucent = drawMaterialKey.isTranslucent(); - bool hasTangents = drawMaterialKey.isNormalMap(); - bool hasLightmap = drawMaterialKey.isLightMap(); - bool isUnlit = drawMaterialKey.isUnlit(); + if (_primitiveMode == PrimitiveMode::LINES) { + builder.withWireframe(); + } - ShapeKey::Builder builder; + auto pipelineType = getPipelineType(mat->second); + if (pipelineType == Pipeline::MATERIAL) { builder.withMaterial(); - if (isTranslucent) { - builder.withTranslucent(); - } - if (hasTangents) { + graphics::MaterialKey drawMaterialKey = mat->second.getMaterialKey(); + if (drawMaterialKey.isNormalMap()) { builder.withTangents(); } - if (hasLightmap) { + if (drawMaterialKey.isLightMap()) { builder.withLightMap(); } - if (isUnlit) { + if (drawMaterialKey.isUnlit()) { builder.withUnlit(); } - - if (_primitiveMode == PrimitiveMode::LINES) { - builder.withWireframe(); - } - - return builder.build(); - } else { - ShapeKey::Builder builder; - bool proceduralReady = resultWithReadLock([&] { - return _procedural.isReady(); - }); - if (proceduralReady) { - builder.withOwnPipeline(); - } - if (isTransparent()) { - builder.withTranslucent(); - } - - if (_primitiveMode == PrimitiveMode::LINES) { - builder.withWireframe(); - } - return builder.build(); + } else if (pipelineType == Pipeline::PROCEDURAL) { + builder.withOwnPipeline(); } + + return builder.build(); } void ShapeEntityRenderer::doRender(RenderArgs* args) { @@ -233,36 +218,36 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { GeometryCache::Shape geometryShape; PrimitiveMode primitiveMode; RenderLayer renderLayer; - bool proceduralRender = false; glm::vec4 outColor; + Pipeline pipelineType; withReadLock([&] { geometryShape = geometryCache->getShapeForEntityShape(_shape); primitiveMode = _primitiveMode; renderLayer = _renderLayer; batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation materials = _materials["0"]; + pipelineType = getPipelineType(materials); auto& schema = materials.getSchemaBuffer().get(); outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); outColor = EntityRenderer::calculatePulseColor(outColor, _pulseProperties, _created); - if (_procedural.isReady()) { - outColor = _procedural.getColor(outColor); - outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; - _procedural.prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); - proceduralRender = true; - } }); if (outColor.a == 0.0f) { return; } - if (proceduralRender) { + if (pipelineType == Pipeline::PROCEDURAL) { + auto procedural = std::static_pointer_cast(materials.top().material); + outColor = procedural->getColor(outColor); + outColor.a *= procedural->isFading() ? Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) : 1.0f; + procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShape(batch, geometryShape, outColor); } else { geometryCache->renderShape(batch, geometryShape, outColor); } - } else if (!useMaterialPipeline(materials)) { + } else if (pipelineType == Pipeline::SIMPLE) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false, diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 6e4b05f716..6061526f75 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -35,14 +35,14 @@ private: virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; - bool useMaterialPipeline(const graphics::MultiMaterial& materials) const; + enum Pipeline { SIMPLE, MATERIAL, PROCEDURAL }; + Pipeline getPipelineType(const graphics::MultiMaterial& materials) const; - Procedural _procedural; - QString _lastUserData; + QString _proceduralData; entity::Shape _shape { entity::Sphere }; PulsePropertyGroup _pulseProperties; - std::shared_ptr _material { std::make_shared() }; + std::shared_ptr _material { std::make_shared() }; glm::vec3 _color { NAN }; float _alpha; diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 56adb59914..3157a6552b 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -6,4 +6,6 @@ include_hifi_library_headers(fbx) include_hifi_library_headers(gpu) include_hifi_library_headers(image) include_hifi_library_headers(ktx) -link_hifi_libraries(shared shaders networking octree avatars graphics material-networking model-networking) +include_hifi_library_headers(material-networking) +include_hifi_library_headers(procedural) +link_hifi_libraries(shared shaders networking octree avatars graphics model-networking) diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index f4f37b1815..9220f301d6 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -119,9 +119,6 @@ protected: Shader(Type type, const Source& source, bool dynamic); Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel); - Shader(const Shader& shader); // deep copy of the sysmem shader - Shader& operator=(const Shader& shader); // deep copy of the sysmem texture - // Source contains the actual source code or nothing if the shader is a program const Source _source; diff --git a/libraries/gpu/src/gpu/ShaderConstants.h b/libraries/gpu/src/gpu/ShaderConstants.h index 1a37c69784..c2637e2dfb 100644 --- a/libraries/gpu/src/gpu/ShaderConstants.h +++ b/libraries/gpu/src/gpu/ShaderConstants.h @@ -21,7 +21,6 @@ #define GPU_TEXTURE_TRANSFORM_OBJECT 31 - #define GPU_RESOURCE_BUFFER_SLOT0_TEXTURE 35 #define GPU_RESOURCE_BUFFER_SLOT1_TEXTURE 36 #define GPU_RESOURCE_BUFFER_SLOT0_STORAGE 0 diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index 1295fc5722..9efaa0a90d 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -66,6 +66,7 @@ namespace scriptable { * @property {string} lightmapParams * @property {string} materialParams * @property {boolean} defaultFallthrough + * @property {string} procedural */ class ScriptableMaterial { public: @@ -101,6 +102,8 @@ namespace scriptable { bool defaultFallthrough; std::unordered_map propertyFallthroughs; // not actually exposed to script + QString procedural; + graphics::MaterialKey key { 0 }; }; diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index ca9634e365..d76c1fcbd2 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -368,129 +368,135 @@ namespace scriptable { obj.setProperty("opacity", material.opacity); } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::GLOSSY_VAL_BIT)) { - obj.setProperty("roughness", FALLTHROUGH); - } else if (material.key.isGlossy()) { - obj.setProperty("roughness", material.roughness); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_VAL_BIT)) { - obj.setProperty("metallic", FALLTHROUGH); - } else if (material.key.isMetallic()) { - obj.setProperty("metallic", material.metallic); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_VAL_BIT)) { - obj.setProperty("scattering", FALLTHROUGH); - } else if (material.key.isScattering()) { - obj.setProperty("scattering", material.scattering); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::UNLIT_VAL_BIT)) { - obj.setProperty("unlit", FALLTHROUGH); - } else if (material.key.isUnlit()) { - obj.setProperty("unlit", material.unlit); - } - - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_VAL_BIT)) { - obj.setProperty("emissive", FALLTHROUGH); - } else if (material.key.isEmissive()) { - obj.setProperty("emissive", vec3ColorToScriptValue(engine, material.emissive)); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ALBEDO_VAL_BIT)) { obj.setProperty("albedo", FALLTHROUGH); } else if (material.key.isAlbedo()) { obj.setProperty("albedo", vec3ColorToScriptValue(engine, material.albedo)); } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_MAP_BIT)) { - obj.setProperty("emissiveMap", FALLTHROUGH); - } else if (!material.emissiveMap.isEmpty()) { - obj.setProperty("emissiveMap", material.emissiveMap); - } + if (material.model.toStdString() == graphics::Material::HIFI_PBR) { + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT)) { + obj.setProperty("opacityCutoff", FALLTHROUGH); + } else if (material.key.isOpacityCutoff()) { + obj.setProperty("opacityCutoff", material.opacityCutoff); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ALBEDO_MAP_BIT)) { - obj.setProperty("albedoMap", FALLTHROUGH); - } else if (!material.albedoMap.isEmpty()) { - obj.setProperty("albedoMap", material.albedoMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_MAP_MODE_BIT)) { + obj.setProperty("opacityMapMode", FALLTHROUGH); + } else if (material.key.isOpacityMapMode()) { + obj.setProperty("opacityMapMode", material.opacityMapMode); + } - if (!material.opacityMap.isEmpty()) { - obj.setProperty("opacityMap", material.opacityMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::GLOSSY_VAL_BIT)) { + obj.setProperty("roughness", FALLTHROUGH); + } else if (material.key.isGlossy()) { + obj.setProperty("roughness", material.roughness); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT | graphics::MaterialKey::OPACITY_MASK_MAP_BIT)) { - obj.setProperty("opacityMapMode", FALLTHROUGH); - } else if (material.key.getOpacityMapMode() != graphics::Material::DEFAULT_OPACITY_MAP_MODE) { - obj.setProperty("opacityMapMode", material.opacityMapMode); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_VAL_BIT)) { + obj.setProperty("metallic", FALLTHROUGH); + } else if (material.key.isMetallic()) { + obj.setProperty("metallic", material.metallic); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT)) { - obj.setProperty("opacityCutoff", FALLTHROUGH); - } else if (material.key.isOpacityCutoff()) { - obj.setProperty("opacityCutoff", material.opacityCutoff); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_VAL_BIT)) { + obj.setProperty("scattering", FALLTHROUGH); + } else if (material.key.isScattering()) { + obj.setProperty("scattering", material.scattering); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OCCLUSION_MAP_BIT)) { - obj.setProperty("occlusionMap", FALLTHROUGH); - } else if (!material.occlusionMap.isEmpty()) { - obj.setProperty("occlusionMap", material.occlusionMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::UNLIT_VAL_BIT)) { + obj.setProperty("unlit", FALLTHROUGH); + } else if (material.key.isUnlit()) { + obj.setProperty("unlit", material.unlit); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::LIGHT_MAP_BIT)) { - obj.setProperty("lightMap", FALLTHROUGH); - } else if (!material.lightMap.isEmpty()) { - obj.setProperty("lightMap", material.lightMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_VAL_BIT)) { + obj.setProperty("emissive", FALLTHROUGH); + } else if (material.key.isEmissive()) { + obj.setProperty("emissive", vec3ColorToScriptValue(engine, material.emissive)); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_MAP_BIT)) { - obj.setProperty("scatteringMap", FALLTHROUGH); - } else if (!material.scatteringMap.isEmpty()) { - obj.setProperty("scatteringMap", material.scatteringMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::EMISSIVE_MAP_BIT)) { + obj.setProperty("emissiveMap", FALLTHROUGH); + } else if (!material.emissiveMap.isEmpty()) { + obj.setProperty("emissiveMap", material.emissiveMap); + } - // Only set one of each of these - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_MAP_BIT)) { - obj.setProperty("metallicMap", FALLTHROUGH); - } else if (!material.metallicMap.isEmpty()) { - obj.setProperty("metallicMap", material.metallicMap); - } else if (!material.specularMap.isEmpty()) { - obj.setProperty("specularMap", material.specularMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ALBEDO_MAP_BIT)) { + obj.setProperty("albedoMap", FALLTHROUGH); + } else if (!material.albedoMap.isEmpty()) { + obj.setProperty("albedoMap", material.albedoMap); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ROUGHNESS_MAP_BIT)) { - obj.setProperty("roughnessMap", FALLTHROUGH); - } else if (!material.roughnessMap.isEmpty()) { - obj.setProperty("roughnessMap", material.roughnessMap); - } else if (!material.glossMap.isEmpty()) { - obj.setProperty("glossMap", material.glossMap); - } + if (!material.opacityMap.isEmpty()) { + obj.setProperty("opacityMap", material.opacityMap); + } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::NORMAL_MAP_BIT)) { - obj.setProperty("normalMap", FALLTHROUGH); - } else if (!material.normalMap.isEmpty()) { - obj.setProperty("normalMap", material.normalMap); - } else if (!material.bumpMap.isEmpty()) { - obj.setProperty("bumpMap", material.bumpMap); - } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::OCCLUSION_MAP_BIT)) { + obj.setProperty("occlusionMap", FALLTHROUGH); + } else if (!material.occlusionMap.isEmpty()) { + obj.setProperty("occlusionMap", material.occlusionMap); + } - // These need to be implemented, but set the fallthrough for now - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) { - obj.setProperty("texCoordTransform0", FALLTHROUGH); - } else if (material.texCoordTransforms[0] != mat4()) { - obj.setProperty("texCoordTransform0", mat4toScriptValue(engine, material.texCoordTransforms[0])); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) { - obj.setProperty("texCoordTransform1", FALLTHROUGH); - } else if (material.texCoordTransforms[1] != mat4()) { - obj.setProperty("texCoordTransform1", mat4toScriptValue(engine, material.texCoordTransforms[1])); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) { - obj.setProperty("lightmapParams", FALLTHROUGH); - } - if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::MATERIAL_PARAMS)) { - obj.setProperty("materialParams", FALLTHROUGH); + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::LIGHT_MAP_BIT)) { + obj.setProperty("lightMap", FALLTHROUGH); + } else if (!material.lightMap.isEmpty()) { + obj.setProperty("lightMap", material.lightMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::SCATTERING_MAP_BIT)) { + obj.setProperty("scatteringMap", FALLTHROUGH); + } else if (!material.scatteringMap.isEmpty()) { + obj.setProperty("scatteringMap", material.scatteringMap); + } + + // Only set one of each of these + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::METALLIC_MAP_BIT)) { + obj.setProperty("metallicMap", FALLTHROUGH); + } else if (!material.metallicMap.isEmpty()) { + obj.setProperty("metallicMap", material.metallicMap); + } else if (!material.specularMap.isEmpty()) { + obj.setProperty("specularMap", material.specularMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::ROUGHNESS_MAP_BIT)) { + obj.setProperty("roughnessMap", FALLTHROUGH); + } else if (!material.roughnessMap.isEmpty()) { + obj.setProperty("roughnessMap", material.roughnessMap); + } else if (!material.glossMap.isEmpty()) { + obj.setProperty("glossMap", material.glossMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::MaterialKey::NORMAL_MAP_BIT)) { + obj.setProperty("normalMap", FALLTHROUGH); + } else if (!material.normalMap.isEmpty()) { + obj.setProperty("normalMap", material.normalMap); + } else if (!material.bumpMap.isEmpty()) { + obj.setProperty("bumpMap", material.bumpMap); + } + + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM0)) { + obj.setProperty("texCoordTransform0", FALLTHROUGH); + } else if (material.texCoordTransforms[0] != mat4()) { + obj.setProperty("texCoordTransform0", mat4toScriptValue(engine, material.texCoordTransforms[0])); + } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::TEXCOORDTRANSFORM1)) { + obj.setProperty("texCoordTransform1", FALLTHROUGH); + } else if (material.texCoordTransforms[1] != mat4()) { + obj.setProperty("texCoordTransform1", mat4toScriptValue(engine, material.texCoordTransforms[1])); + } + + // These need to be implemented, but set the fallthrough for now + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::LIGHTMAP_PARAMS)) { + obj.setProperty("lightmapParams", FALLTHROUGH); + } + if (hasPropertyFallthroughs && material.propertyFallthroughs.at(graphics::Material::MATERIAL_PARAMS)) { + obj.setProperty("materialParams", FALLTHROUGH); + } + + } else if (material.model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { + obj.setProperty("procedural", material.procedural); } obj.setProperty("defaultFallthrough", material.defaultFallthrough); diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp index bc610108ec..4a56db0d04 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.cpp @@ -23,27 +23,31 @@ scriptable::ScriptableMaterial& scriptable::ScriptableMaterial::operator=(const name = material.name; model = material.model; opacity = material.opacity; - roughness = material.roughness; - metallic = material.metallic; - scattering = material.scattering; - opacityCutoff = material.opacityCutoff; - unlit = material.unlit; - emissive = material.emissive; albedo = material.albedo; - emissiveMap = material.emissiveMap; - albedoMap = material.albedoMap; - opacityMap = material.opacityMap; - metallicMap = material.metallicMap; - specularMap = material.specularMap; - roughnessMap = material.roughnessMap; - glossMap = material.glossMap; - normalMap = material.normalMap; - bumpMap = material.bumpMap; - occlusionMap = material.occlusionMap; - lightMap = material.lightMap; - scatteringMap = material.scatteringMap; - opacityMapMode = material.opacityMapMode; + if (model.toStdString() == graphics::Material::HIFI_PBR) { + opacityCutoff = material.opacityCutoff; + opacityMapMode = material.opacityMapMode; + roughness = material.roughness; + metallic = material.metallic; + scattering = material.scattering; + unlit = material.unlit; + emissive = material.emissive; + emissiveMap = material.emissiveMap; + albedoMap = material.albedoMap; + opacityMap = material.opacityMap; + metallicMap = material.metallicMap; + specularMap = material.specularMap; + roughnessMap = material.roughnessMap; + glossMap = material.glossMap; + normalMap = material.normalMap; + bumpMap = material.bumpMap; + occlusionMap = material.occlusionMap; + lightMap = material.lightMap; + scatteringMap = material.scatteringMap; + } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { + procedural = material.procedural; + } defaultFallthrough = material.defaultFallthrough; propertyFallthroughs = material.propertyFallthroughs; @@ -58,77 +62,83 @@ scriptable::ScriptableMaterial::ScriptableMaterial(const graphics::MaterialPoint name = material->getName().c_str(); model = material->getModel().c_str(); opacity = material->getOpacity(); - - opacityMapMode = QString(graphics::MaterialKey::getOpacityMapModeName(material->getOpacityMapMode()).c_str()); - roughness = material->getRoughness(); - metallic = material->getMetallic(); - scattering = material->getScattering(); - opacityCutoff = material->getOpacityCutoff(); - unlit = material->isUnlit(); - emissive = material->getEmissive(); albedo = material->getAlbedo(); + + if (model.toStdString() == graphics::Material::HIFI_PBR) { + opacityCutoff = material->getOpacityCutoff(); + opacityMapMode = QString(graphics::MaterialKey::getOpacityMapModeName(material->getOpacityMapMode()).c_str()); + roughness = material->getRoughness(); + metallic = material->getMetallic(); + scattering = material->getScattering(); + unlit = material->isUnlit(); + emissive = material->getEmissive(); + + auto map = material->getTextureMap(graphics::Material::MapChannel::EMISSIVE_MAP); + if (map && map->getTextureSource()) { + emissiveMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::ALBEDO_MAP); + if (map && map->getTextureSource()) { + albedoMap = map->getTextureSource()->getUrl().toString(); + if (map->useAlphaChannel()) { + opacityMap = albedoMap; + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::METALLIC_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::METALLIC_TEXTURE) { + metallicMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::SPECULAR_TEXTURE) { + specularMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::ROUGHNESS_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::ROUGHNESS_TEXTURE) { + roughnessMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::GLOSS_TEXTURE) { + glossMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::NORMAL_MAP); + if (map && map->getTextureSource()) { + if (map->getTextureSource()->getType() == image::TextureUsage::Type::NORMAL_TEXTURE) { + normalMap = map->getTextureSource()->getUrl().toString(); + } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::BUMP_TEXTURE) { + bumpMap = map->getTextureSource()->getUrl().toString(); + } + } + + map = material->getTextureMap(graphics::Material::MapChannel::OCCLUSION_MAP); + if (map && map->getTextureSource()) { + occlusionMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::LIGHT_MAP); + if (map && map->getTextureSource()) { + lightMap = map->getTextureSource()->getUrl().toString(); + } + + map = material->getTextureMap(graphics::Material::MapChannel::SCATTERING_MAP); + if (map && map->getTextureSource()) { + scatteringMap = map->getTextureSource()->getUrl().toString(); + } + + for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { + texCoordTransforms[i] = material->getTexCoordTransform(i); + } + } else if (model.toStdString() == graphics::Material::HIFI_SHADER_SIMPLE) { + procedural = material->getProceduralString(); + } + defaultFallthrough = material->getDefaultFallthrough(); propertyFallthroughs = material->getPropertyFallthroughs(); + key = material->getKey(); - - auto map = material->getTextureMap(graphics::Material::MapChannel::EMISSIVE_MAP); - if (map && map->getTextureSource()) { - emissiveMap = map->getTextureSource()->getUrl().toString(); - } - - map = material->getTextureMap(graphics::Material::MapChannel::ALBEDO_MAP); - if (map && map->getTextureSource()) { - albedoMap = map->getTextureSource()->getUrl().toString(); - if (map->useAlphaChannel()) { - opacityMap = albedoMap; - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::METALLIC_MAP); - if (map && map->getTextureSource()) { - if (map->getTextureSource()->getType() == image::TextureUsage::Type::METALLIC_TEXTURE) { - metallicMap = map->getTextureSource()->getUrl().toString(); - } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::SPECULAR_TEXTURE) { - specularMap = map->getTextureSource()->getUrl().toString(); - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::ROUGHNESS_MAP); - if (map && map->getTextureSource()) { - if (map->getTextureSource()->getType() == image::TextureUsage::Type::ROUGHNESS_TEXTURE) { - roughnessMap = map->getTextureSource()->getUrl().toString(); - } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::GLOSS_TEXTURE) { - glossMap = map->getTextureSource()->getUrl().toString(); - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::NORMAL_MAP); - if (map && map->getTextureSource()) { - if (map->getTextureSource()->getType() == image::TextureUsage::Type::NORMAL_TEXTURE) { - normalMap = map->getTextureSource()->getUrl().toString(); - } else if (map->getTextureSource()->getType() == image::TextureUsage::Type::BUMP_TEXTURE) { - bumpMap = map->getTextureSource()->getUrl().toString(); - } - } - - map = material->getTextureMap(graphics::Material::MapChannel::OCCLUSION_MAP); - if (map && map->getTextureSource()) { - occlusionMap = map->getTextureSource()->getUrl().toString(); - } - - map = material->getTextureMap(graphics::Material::MapChannel::LIGHT_MAP); - if (map && map->getTextureSource()) { - lightMap = map->getTextureSource()->getUrl().toString(); - } - - map = material->getTextureMap(graphics::Material::MapChannel::SCATTERING_MAP); - if (map && map->getTextureSource()) { - scatteringMap = map->getTextureSource()->getUrl().toString(); - } - - for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { - texCoordTransforms[i] = material->getTexCoordTransform(i); - } } } diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index dffc52e29f..d80c3adfbc 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -34,7 +34,6 @@ std::string MaterialKey::getOpacityMapModeName(OpacityMapMode mode) { return names[mode]; } - bool MaterialKey::getOpacityMapModeFromName(const std::string& modeName, MaterialKey::OpacityMapMode& mode) { for (int i = OPACITY_MAP_OPAQUE; i <= OPACITY_MAP_BLEND; i++) { mode = (MaterialKey::OpacityMapMode) i; @@ -45,6 +44,9 @@ bool MaterialKey::getOpacityMapModeFromName(const std::string& modeName, Materia return false; } +const std::string Material::HIFI_PBR { "hifi_pbr" }; +const std::string Material::HIFI_SHADER_SIMPLE { "hifi_shader_simple" }; + Material::Material() { for (int i = 0; i < NUM_TOTAL_FLAGS; i++) { _propertyFallthroughs[i] = false; diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 25ff711c0c..48ab8151c5 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -328,6 +328,7 @@ public: Material(); Material(const Material& material); + virtual ~Material() = default; Material& operator= (const Material& material); const MaterialKey& getKey() const { return _key; } @@ -409,11 +410,19 @@ public: bool getPropertyFallthrough(uint property) { return _propertyFallthroughs[property]; } void setPropertyDoesFallthrough(uint property) { _propertyFallthroughs[property] = true; } + virtual bool isProcedural() const { return false; } + virtual bool isEnabled() const { return true; } + virtual bool isReady() const { return true; } + virtual QString getProceduralString() const { return QString(); } + + static const std::string HIFI_PBR; + static const std::string HIFI_SHADER_SIMPLE; + protected: std::string _name { "" }; private: - std::string _model { "hifi_pbr" }; + std::string _model { HIFI_PBR }; mutable MaterialKey _key { 0 }; // Material properties diff --git a/libraries/model-baker/CMakeLists.txt b/libraries/model-baker/CMakeLists.txt index 6c0f220340..bf75db4750 100644 --- a/libraries/model-baker/CMakeLists.txt +++ b/libraries/model-baker/CMakeLists.txt @@ -1,7 +1,8 @@ set(TARGET_NAME model-baker) setup_hifi_library() -link_hifi_libraries(shared shaders task gpu graphics hfm material-networking) +link_hifi_libraries(shared shaders task gpu graphics hfm procedural) +include_hifi_library_headers(material-networking) include_hifi_library_headers(networking) include_hifi_library_headers(image) include_hifi_library_headers(ktx) diff --git a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h index 7c94661b28..3e967a7d3f 100644 --- a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h @@ -18,7 +18,7 @@ #include "Engine.h" #include "BakerTypes.h" -#include +#include class ParseMaterialMappingTask { public: diff --git a/libraries/model-networking/CMakeLists.txt b/libraries/model-networking/CMakeLists.txt index e79d18f779..b71d125586 100644 --- a/libraries/model-networking/CMakeLists.txt +++ b/libraries/model-networking/CMakeLists.txt @@ -1,8 +1,9 @@ set(TARGET_NAME model-networking) setup_hifi_library() -link_hifi_libraries(shared shaders networking graphics fbx material-networking model-baker) +link_hifi_libraries(shared shaders networking graphics fbx procedural model-baker) include_hifi_library_headers(hfm) include_hifi_library_headers(task) include_hifi_library_headers(gpu) include_hifi_library_headers(image) -include_hifi_library_headers(ktx) \ No newline at end of file +include_hifi_library_headers(ktx) +include_hifi_library_headers(material-networking) \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 87dbbe975d..d61bd61696 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -18,7 +18,7 @@ #include #include "FBXSerializer.h" -#include +#include #include #include "ModelLoader.h" diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index d7ce40641d..c1410a6bfc 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -1,17 +1,18 @@ set(TARGET_NAME physics) setup_hifi_library() -link_hifi_libraries(shared task workload fbx entities graphics shaders) +link_hifi_libraries(shared workload entities shaders) include_hifi_library_headers(networking) include_hifi_library_headers(gpu) include_hifi_library_headers(avatars) -include_hifi_library_headers(audio) include_hifi_library_headers(octree) -include_hifi_library_headers(animation) include_hifi_library_headers(material-networking) include_hifi_library_headers(model-networking) +include_hifi_library_headers(procedural) include_hifi_library_headers(image) include_hifi_library_headers(ktx) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) +include_hifi_library_headers(fbx) +include_hifi_library_headers(graphics) target_bullet() diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index d08a7aef02..d737d34e95 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME procedural) setup_hifi_library() -link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image) +link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image hfm) diff --git a/libraries/material-networking/src/material-networking/MaterialCacheScriptingInterface.cpp b/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.cpp similarity index 90% rename from libraries/material-networking/src/material-networking/MaterialCacheScriptingInterface.cpp rename to libraries/procedural/src/procedural/MaterialCacheScriptingInterface.cpp index 193d9b96ee..77eceaa10b 100644 --- a/libraries/material-networking/src/material-networking/MaterialCacheScriptingInterface.cpp +++ b/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.cpp @@ -1,6 +1,5 @@ // // MaterialCacheScriptingInterface.cpp -// libraries/mmodel-networking/src/model-networking // // Created by Sam Gateau on 17 September 2019. // Copyright 2019 High Fidelity, Inc. diff --git a/libraries/material-networking/src/material-networking/MaterialCacheScriptingInterface.h b/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.h similarity index 81% rename from libraries/material-networking/src/material-networking/MaterialCacheScriptingInterface.h rename to libraries/procedural/src/procedural/MaterialCacheScriptingInterface.h index c619966a2a..3a13652aec 100644 --- a/libraries/material-networking/src/material-networking/MaterialCacheScriptingInterface.h +++ b/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.h @@ -1,6 +1,5 @@ // -// MaterialCacheScriptingInterface.h -// libraries/material-networking/src/material-networking +// ProceduralMaterialCacheScriptingInterface.h // // Created by Sam Gateau on 17 September 2019. // Copyright 2019 High Fidelity, Inc. @@ -10,14 +9,14 @@ // #pragma once -#ifndef hifi_MaterialCacheScriptingInterface_h -#define hifi_MaterialCacheScriptingInterface_h +#ifndef hifi_ProceduralMaterialCacheScriptingInterface_h +#define hifi_ProceduralMaterialCacheScriptingInterface_h #include #include -#include "MaterialCache.h" +#include "ProceduralMaterialCache.h" class MaterialCacheScriptingInterface : public ScriptableResourceCache, public Dependency { Q_OBJECT @@ -27,7 +26,7 @@ class MaterialCacheScriptingInterface : public ScriptableResourceCache, public D /**jsdoc * The TextureCache API manages texture cache resources. * - * @namespace TextureCache + * @namespace MaterialCache * * @hifi-interface * @hifi-client-entity @@ -48,4 +47,4 @@ public: MaterialCacheScriptingInterface(); }; -#endif // hifi_MaterialCacheScriptingInterface_h +#endif // hifi_ProceduralMaterialCacheScriptingInterface_h diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index ce4fbb2a38..43c6b25dcb 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -29,6 +29,7 @@ Q_LOGGING_CATEGORY(proceduralLog, "hifi.gpu.procedural") // User-data parsing constants static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity"; +static const QString FRAGMENT_URL_KEY = "fragmentShaderURL"; static const QString URL_KEY = "shaderUrl"; static const QString VERSION_KEY = "version"; static const QString UNIFORMS_KEY = "uniforms"; @@ -40,7 +41,7 @@ static const std::string PROCEDURAL_VERSION = "//PROCEDURAL_VERSION"; bool operator==(const ProceduralData& a, const ProceduralData& b) { return ((a.version == b.version) && - (a.shaderUrl == b.shaderUrl) && + (a.fragmentShaderUrl == b.fragmentShaderUrl) && (a.uniforms == b.uniforms) && (a.channels == b.channels)); } @@ -56,7 +57,13 @@ QJsonValue ProceduralData::getProceduralData(const QString& proceduralJson) { return QJsonValue(); } - return doc.object()[PROCEDURAL_USER_DATA_KEY]; + auto object = doc.object(); + auto userDataIt = object.find(PROCEDURAL_USER_DATA_KEY); + if (userDataIt != object.end()) { + return userDataIt.value(); + } + + return object; } ProceduralData ProceduralData::parse(const QString& proceduralData) { @@ -84,11 +91,18 @@ void ProceduralData::parse(const QJsonObject& proceduralData) { } } - auto rawShaderUrl = proceduralData[URL_KEY].toString(); - shaderUrl = DependencyManager::get()->normalizeURL(rawShaderUrl); + { // Fragment shader URL (either fragmentShaderURL or shaderUrl) + auto rawShaderUrl = proceduralData[FRAGMENT_URL_KEY].toString(); + fragmentShaderUrl = DependencyManager::get()->normalizeURL(rawShaderUrl); + + if (fragmentShaderUrl.isEmpty()) { + rawShaderUrl = proceduralData[URL_KEY].toString(); + fragmentShaderUrl = DependencyManager::get()->normalizeURL(rawShaderUrl); + } + } // Empty shader URL isn't valid - if (shaderUrl.isEmpty()) { + if (fragmentShaderUrl.isEmpty()) { return; } @@ -96,12 +110,8 @@ void ProceduralData::parse(const QJsonObject& proceduralData) { channels = proceduralData[CHANNELS_KEY].toArray(); } -// Example -//{ -// "ProceduralEntity": { -// "shaderUrl": "file:///C:/Users/bdavis/Git/hifi/examples/shaders/test.fs", -// } -//} +std::function Procedural::opaqueStencil = [](gpu::StatePointer state) {}; +std::function Procedural::transparentStencil = [](gpu::StatePointer state) {}; Procedural::Procedural() { _opaqueState->setCullMode(gpu::State::CULL_NONE); @@ -109,12 +119,14 @@ Procedural::Procedural() { _opaqueState->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + opaqueStencil(_opaqueState); _transparentState->setCullMode(gpu::State::CULL_NONE); _transparentState->setDepthTest(true, true, gpu::LESS_EQUAL); _transparentState->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + transparentStencil(_transparentState); _standardInputsBuffer = std::make_shared(sizeof(StandardInputs), nullptr); } @@ -158,14 +170,14 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) { } } - if (proceduralData.shaderUrl != _data.shaderUrl) { - _data.shaderUrl = proceduralData.shaderUrl; - const auto& shaderUrl = _data.shaderUrl; + if (proceduralData.fragmentShaderUrl != _data.fragmentShaderUrl) { + _data.fragmentShaderUrl = proceduralData.fragmentShaderUrl; + const auto& shaderUrl = _data.fragmentShaderUrl; _shaderDirty = true; - _networkShader.reset(); - _shaderPath.clear(); - _shaderSource.clear(); + _networkFragmentShader.reset(); + _fragmentShaderPath.clear(); + _fragmentShaderSource.clear(); if (shaderUrl.isEmpty() || !shaderUrl.isValid()) { return; @@ -175,11 +187,11 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) { if (!QFileInfo(shaderUrl.toLocalFile()).exists()) { return; } - _shaderPath = shaderUrl.toLocalFile(); + _fragmentShaderPath = shaderUrl.toLocalFile(); } else if (shaderUrl.scheme() == URL_SCHEME_QRC) { - _shaderPath = ":" + shaderUrl.path(); + _fragmentShaderPath = ":" + shaderUrl.path(); } else { - _networkShader = ShaderCache::instance().getShader(shaderUrl); + _networkFragmentShader = ShaderCache::instance().getShader(shaderUrl); } } @@ -202,7 +214,7 @@ bool Procedural::isReady() const { } // Do we have a network or local shader, and if so, is it loaded? - if (_shaderPath.isEmpty() && (!_networkShader || !_networkShader->isLoaded())) { + if (_fragmentShaderPath.isEmpty() && (!_networkFragmentShader || !_networkFragmentShader->isLoaded())) { return false; } @@ -232,17 +244,17 @@ void Procedural::prepare(gpu::Batch& batch, _entityPosition = position; _entityOrientation = glm::mat3_cast(orientation); _entityCreated = created; - if (!_shaderPath.isEmpty()) { - auto lastModified = (uint64_t)QFileInfo(_shaderPath).lastModified().toMSecsSinceEpoch(); - if (lastModified > _shaderModified) { - QFile file(_shaderPath); + if (!_fragmentShaderPath.isEmpty()) { + auto lastModified = (uint64_t)QFileInfo(_fragmentShaderPath).lastModified().toMSecsSinceEpoch(); + if (lastModified > _fragmentShaderModified) { + QFile file(_fragmentShaderPath); file.open(QIODevice::ReadOnly); - _shaderSource = QTextStream(&file).readAll(); + _fragmentShaderSource = QTextStream(&file).readAll(); _shaderDirty = true; - _shaderModified = lastModified; + _fragmentShaderModified = lastModified; } - } else if (_shaderSource.isEmpty() && _networkShader && _networkShader->isLoaded()) { - _shaderSource = _networkShader->_source; + } else if (_fragmentShaderSource.isEmpty() && _networkFragmentShader && _networkFragmentShader->isLoaded()) { + _fragmentShaderSource = _networkFragmentShader->_source; _shaderDirty = true; } @@ -253,8 +265,13 @@ void Procedural::prepare(gpu::Batch& batch, auto pipeline = _proceduralPipelines.find(key); bool recompiledShader = false; if (pipeline == _proceduralPipelines.end()) { - if (!_vertexShader) { - _vertexShader = gpu::Shader::createVertex(_vertexSource); + gpu::Shader::Source vertexSource; + if (key.isSkinnedDQ()) { + vertexSource = _vertexSourceSkinnedDQ; + } else if (key.isSkinned()) { + vertexSource = _vertexSourceSkinned; + } else { + vertexSource = _vertexSource; } gpu::Shader::Source& fragmentSource = (key.isTransparent() && _transparentFragmentSource.valid()) ? _transparentFragmentSource : _opaqueFragmentSource; @@ -262,7 +279,7 @@ void Procedural::prepare(gpu::Batch& batch, // Build the fragment shader fragmentSource.replacements.clear(); fragmentSource.replacements[PROCEDURAL_VERSION] = "#define PROCEDURAL_V" + std::to_string(_data.version); - fragmentSource.replacements[PROCEDURAL_BLOCK] = _shaderSource.toStdString(); + fragmentSource.replacements[PROCEDURAL_BLOCK] = _fragmentShaderSource.toStdString(); // Set any userdata specified uniforms (if any) if (!_data.uniforms.empty()) { @@ -287,8 +304,9 @@ void Procedural::prepare(gpu::Batch& batch, // Leave this here for debugging //qCDebug(proceduralLog) << "FragmentShader:\n" << fragmentSource.getSource(shader::Dialect::glsl450, shader::Variant::Mono).c_str(); + gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(vertexSource); gpu::ShaderPointer fragmentShader = gpu::Shader::createPixel(fragmentSource); - gpu::ShaderPointer program = gpu::Shader::createProgram(_vertexShader, fragmentShader); + gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, fragmentShader); _proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState); @@ -303,10 +321,12 @@ void Procedural::prepare(gpu::Batch& batch, // FIXME: need to handle forward rendering batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second); - if (_shaderDirty || _uniformsDirty) { + bool recreateUniforms = _shaderDirty || _uniformsDirty || recompiledShader || _prevKey != key; + if (recreateUniforms) { setupUniforms(); } + _prevKey = key; _shaderDirty = _uniformsDirty = false; for (auto lambda : _uniforms) { @@ -341,7 +361,7 @@ void Procedural::setupUniforms() { QJsonValue value = _data.uniforms[key]; if (value.isDouble()) { float v = value.toDouble(); - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); } else if (value.isArray()) { auto valueArray = value.toArray(); switch (valueArray.size()) { @@ -350,13 +370,13 @@ void Procedural::setupUniforms() { case 1: { float v = valueArray[0].toDouble(); - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform1f(slot, v); }); break; } case 2: { glm::vec2 v{ valueArray[0].toDouble(), valueArray[1].toDouble() }; - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform2f(slot, v.x, v.y); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform2f(slot, v.x, v.y); }); break; } @@ -366,7 +386,7 @@ void Procedural::setupUniforms() { valueArray[1].toDouble(), valueArray[2].toDouble(), }; - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform3f(slot, v.x, v.y, v.z); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform3f(slot, v.x, v.y, v.z); }); break; } @@ -378,7 +398,7 @@ void Procedural::setupUniforms() { valueArray[2].toDouble(), valueArray[3].toDouble(), }; - _uniforms.push_back([=](gpu::Batch& batch) { batch._glUniform4f(slot, v.x, v.y, v.z, v.w); }); + _uniforms.push_back([slot, v](gpu::Batch& batch) { batch._glUniform4f(slot, v.x, v.y, v.z, v.w); }); break; } } @@ -386,7 +406,7 @@ void Procedural::setupUniforms() { slot++; } - _uniforms.push_back([=](gpu::Batch& batch) { + _uniforms.push_back([this](gpu::Batch& batch) { _standardInputs.position = vec4(_entityPosition, 1.0f); // Minimize floating point error by doing an integer division to milliseconds, before the floating point division to seconds auto now = usecTimestampNow(); @@ -422,7 +442,7 @@ void Procedural::setupUniforms() { } _standardInputsBuffer->setSubData(0, _standardInputs); - batch.setUniformBuffer(0, _standardInputsBuffer, 0, sizeof(StandardInputs)); + batch.setUniformBuffer(procedural::slot::buffer::Inputs, _standardInputsBuffer, 0, sizeof(StandardInputs)); }); } @@ -432,3 +452,13 @@ glm::vec4 Procedural::getColor(const glm::vec4& entityColor) const { } return entityColor; } + +void graphics::ProceduralMaterial::initializeProcedural() { + _procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural); + _procedural._vertexSourceSkinned = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformed); + _procedural._vertexSourceSkinnedDQ = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple_procedural_deformeddq); + + // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering + _procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural); + _procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent); +} \ No newline at end of file diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 956cef368f..aac353bf7c 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -21,11 +21,26 @@ #include #include #include +#include "ProceduralMaterialCache.h" using UniformLambdas = std::list>; const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; +/**jsdoc + * An object containing user-defined uniforms for communicating data to shaders. + * @typedef {object} ProceduralUniforms + */ + +/**jsdoc + * The data used to define a Procedural shader material. + * @typedef {object} ProceduralData + * @property {number} version=1 - The version of the procedural shader. + * @property {string} fragmentShaderURL - A link to a fragment shader. Currently, only GLSL shaders are supported. The shader must implement a different method depending on the version. + * shaderUrl is an alias. + * @property {string[]} channels=[] - An array of input texture URLs. Currently, up to 4 are supported. + * @property {ProceduralUniforms} uniforms={} - A {@link ProceduralUniforms} object containing all the custom uniforms to be passed to the shader. + */ struct ProceduralData { static QJsonValue getProceduralData(const QString& proceduralJson); @@ -34,7 +49,7 @@ struct ProceduralData { // Rendering object descriptions, from userData uint8_t version { 0 }; - QUrl shaderUrl; + QUrl fragmentShaderUrl; QJsonObject uniforms; QJsonArray channels; }; @@ -43,19 +58,23 @@ class ProceduralProgramKey { public: enum FlagBit { IS_TRANSPARENT = 0, + IS_SKINNED, + IS_SKINNED_DQ, + NUM_FLAGS }; - typedef std::bitset Flags; Flags _flags; bool isTransparent() const { return _flags[IS_TRANSPARENT]; } + bool isSkinned() const { return _flags[IS_SKINNED]; } + bool isSkinnedDQ() const { return _flags[IS_SKINNED_DQ]; } - ProceduralProgramKey(bool transparent = false) { - if (transparent) { - _flags.set(IS_TRANSPARENT); - } + ProceduralProgramKey(bool transparent = false, bool isSkinned = false, bool isSkinnedDQ = false) { + _flags.set(IS_TRANSPARENT, transparent); + _flags.set(IS_SKINNED, isSkinned); + _flags.set(IS_SKINNED_DQ, isSkinnedDQ); } }; namespace std { @@ -92,12 +111,16 @@ public: void setDoesFade(bool doesFade) { _doesFade = doesFade; } gpu::Shader::Source _vertexSource; + gpu::Shader::Source _vertexSourceSkinned; + gpu::Shader::Source _vertexSourceSkinnedDQ; gpu::Shader::Source _opaqueFragmentSource; gpu::Shader::Source _transparentFragmentSource; gpu::StatePointer _opaqueState { std::make_shared() }; gpu::StatePointer _transparentState { std::make_shared() }; + static std::function opaqueStencil; + static std::function transparentStencil; protected: // DO NOT TOUCH @@ -134,10 +157,10 @@ protected: int32_t _frameCount { 0 }; // Rendering object descriptions, from userData - QString _shaderSource; - QString _shaderPath; - uint64_t _shaderModified { 0 }; - NetworkShaderPointer _networkShader; + QString _fragmentShaderSource; + QString _fragmentShaderPath; + uint64_t _fragmentShaderModified { 0 }; + NetworkShaderPointer _networkFragmentShader; bool _shaderDirty { true }; bool _uniformsDirty { true }; @@ -147,8 +170,6 @@ protected: std::unordered_map _proceduralPipelines; - gpu::ShaderPointer _vertexShader; - StandardInputs _standardInputs; gpu::BufferPointer _standardInputsBuffer; @@ -165,5 +186,41 @@ private: mutable bool _hasStartedFade { false }; mutable bool _isFading { false }; bool _doesFade { true }; + ProceduralProgramKey _prevKey; mutable std::mutex _mutex; }; + +namespace graphics { + +class ProceduralMaterial : public NetworkMaterial { +public: + ProceduralMaterial() : NetworkMaterial() { initializeProcedural(); } + ProceduralMaterial(const NetworkMaterial& material) : NetworkMaterial(material) { initializeProcedural(); } + + bool isProcedural() const override { return true; } + bool isEnabled() const override { return _procedural.isEnabled(); } + bool isReady() const override { return _procedural.isReady(); } + QString getProceduralString() const override { return _proceduralString; } + + void setProceduralData(const QString& data) { + _proceduralString = data; + _procedural.setProceduralData(ProceduralData::parse(data)); + } + glm::vec4 getColor(const glm::vec4& color) const { return _procedural.getColor(color); } + bool isFading() const { return _procedural.isFading(); } + void setIsFading(bool isFading) { _procedural.setIsFading(isFading); } + uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); } + void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, + const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) { + _procedural.prepare(batch, position, size, orientation, created, key); + } + + void initializeProcedural(); + +private: + QString _proceduralString; + Procedural _procedural; +}; +typedef std::shared_ptr ProceduralMaterialPointer; + +} \ No newline at end of file diff --git a/libraries/procedural/src/procedural/ProceduralCommon.slh b/libraries/procedural/src/procedural/ProceduralCommon.slh index 6e73534440..2915f096e6 100644 --- a/libraries/procedural/src/procedural/ProceduralCommon.slh +++ b/libraries/procedural/src/procedural/ProceduralCommon.slh @@ -24,7 +24,7 @@ LAYOUT(binding=PROCEDURAL_TEXTURE_CHANNEL3) uniform sampler2D iChannel3; // comptability with existing procedural shaders that previously relied on these // inputs as uniforms, not members of a UBO -LAYOUT_STD140(binding=0) uniform standardInputsBuffer { +LAYOUT_STD140(binding=PROCEDURAL_BUFFER_INPUTS) uniform standardInputsBuffer { // Offset 0 vec4 date; // Offset 16, acts as vec4 for alignment purposes diff --git a/libraries/material-networking/src/material-networking/MaterialCache.cpp b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp similarity index 90% rename from libraries/material-networking/src/material-networking/MaterialCache.cpp rename to libraries/procedural/src/procedural/ProceduralMaterialCache.cpp index db4783d249..b9611358e7 100644 --- a/libraries/material-networking/src/material-networking/MaterialCache.cpp +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp @@ -5,7 +5,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "MaterialCache.h" +#include "ProceduralMaterialCache.h" #include "QJsonObject" #include "QJsonDocument" @@ -13,6 +13,8 @@ #include "RegisteredMetaTypes.h" +#include "Procedural.h" + NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) : Resource(url) {} @@ -112,20 +114,22 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater * A material used in a {@link Entities.MaterialResource|MaterialResource}. * @typedef {object} Entities.Material * @property {string} model="hifi_pbr" - Different material models support different properties and rendering modes. - * Supported models are: "hifi_pbr". + * Supported models are: "hifi_pbr", "hifi_shader_simple". * @property {string} name="" - A name for the material. Supported by all material models. * @property {ColorFloat|RGBS|string} emissive - The emissive color, i.e., the color that the material emits. A * {@link ColorFloat} value is treated as sRGB and must have component values in the range 0.0 – * 1.0. A {@link RGBS} value can be either RGB or sRGB. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {number|string} opacity=1.0 - The opacity, range 0.01.0. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. + * @property {number|string} opacity=1.0 - The opacity, range 0.01.0. + * Set to "fallthrough" to fall through to the material below. "hifi_pbr" and + * "hifi_shader_simple" models only. * @property {boolean|string} unlit=false - true if the material is unaffected by lighting, false if * it is lit by the key light and local lights. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have - * component values in the range 0.01.0. A {@link RGBS} value can be either RGB or sRGB. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. + * @property {ColorFloat|RGBS|string} albedo - The albedo color. A {@link ColorFloat} value is treated as sRGB and must have + * component values in the range 0.01.0. A {@link RGBS} value can be either RGB or sRGB. + * Set to "fallthrough" to fall through to the material below. "hifi_pbr" and + * "hifi_shader_simple" models only. * @property {number|string} roughness - The roughness, range 0.01.0. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. * @property {number|string} metallic - The metallicness, range 0.01.0. @@ -183,25 +187,25 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater *

Currently not used.

* @property {boolean} defaultFallthrough=false - true if all properties fall through to the material below * unless they are set, false if properties respect their individual fall-through settings. - * "hifi_pbr" model only. + * "hifi_pbr" and "hifi_shader_simple" models only. + * @property {ProceduralData} procedural - The definition of a procedural shader material. "hifi_shader_simple" model only. */ // Note: See MaterialEntityItem.h for default values used in practice. std::pair> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl) { std::string name = ""; - std::shared_ptr material = std::make_shared(); + std::shared_ptr networkMaterial; - const std::string HIFI_PBR = "hifi_pbr"; - std::string modelString = HIFI_PBR; + std::string modelString = graphics::Material::HIFI_PBR; auto modelJSONIter = materialJSON.find("model"); if (modelJSONIter != materialJSON.end() && modelJSONIter.value().isString()) { modelString = modelJSONIter.value().toString().toStdString(); - material->setModel(modelString); } std::array texcoordTransforms; - if (modelString == HIFI_PBR) { - const QString FALLTHROUGH("fallthrough"); + const QString FALLTHROUGH("fallthrough"); + if (modelString == graphics::Material::HIFI_PBR) { + auto material = std::make_shared(); for (auto& key : materialJSON.keys()) { if (key == "name") { auto nameJSON = materialJSON.value(key); @@ -209,11 +213,6 @@ std::pair> NetworkMaterialResource name = nameJSON.toString().toStdString(); material->setName(name); } - } else if (key == "model") { - auto modelJSON = materialJSON.value(key); - if (modelJSON.isString()) { - material->setModel(modelJSON.toString().toStdString()); - } } else if (key == "emissive") { auto value = materialJSON.value(key); if (value.isString() && value.toString() == FALLTHROUGH) { @@ -268,13 +267,15 @@ std::pair> NetworkMaterialResource } } else if (key == "opacityMapMode") { auto value = materialJSON.value(key); - auto valueString = (value.isString() ? value.toString() : ""); - if (valueString == FALLTHROUGH) { - material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_MAP_MODE_BIT); - } else { - graphics::MaterialKey::OpacityMapMode mode; - if (graphics::MaterialKey::getOpacityMapModeFromName(valueString.toStdString(), mode)) { - material->setOpacityMapMode(mode); + if (value.isString()) { + auto valueString = value.toString(); + if (valueString == FALLTHROUGH) { + material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_MAP_MODE_BIT); + } else { + graphics::MaterialKey::OpacityMapMode mode; + if (graphics::MaterialKey::getOpacityMapModeFromName(valueString.toStdString(), mode)) { + material->setOpacityMapMode(mode); + } } } } else if (key == "opacityCutoff") { @@ -455,17 +456,61 @@ std::pair> NetworkMaterialResource } } } - } - // Do this after the texture maps are defined, so it overrides the default transforms - for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { - mat4 newTransform = texcoordTransforms[i]; - if (newTransform != mat4() || newTransform != material->getTexCoordTransform(i)) { - material->setTexCoordTransform(i, newTransform); + // Do this after the texture maps are defined, so it overrides the default transforms + for (int i = 0; i < graphics::Material::NUM_TEXCOORD_TRANSFORMS; i++) { + mat4 newTransform = texcoordTransforms[i]; + if (newTransform != mat4() || newTransform != material->getTexCoordTransform(i)) { + material->setTexCoordTransform(i, newTransform); + } } + networkMaterial = material; + } else if (modelString == graphics::Material::HIFI_SHADER_SIMPLE) { + auto material = std::make_shared(); + for (auto& key : materialJSON.keys()) { + if (key == "name") { + auto nameJSON = materialJSON.value(key); + if (nameJSON.isString()) { + name = nameJSON.toString().toStdString(); + material->setName(name); + } + } else if (key == "opacity") { + auto value = materialJSON.value(key); + if (value.isString() && value.toString() == FALLTHROUGH) { + material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::OPACITY_VAL_BIT); + } else if (value.isDouble()) { + material->setOpacity(value.toDouble()); + } + } else if (key == "albedo") { + auto value = materialJSON.value(key); + if (value.isString() && value.toString() == FALLTHROUGH) { + material->setPropertyDoesFallthrough(graphics::MaterialKey::FlagBit::ALBEDO_VAL_BIT); + } else { + glm::vec3 color; + bool isSRGB; + bool valid = parseJSONColor(value, color, isSRGB); + if (valid) { + material->setAlbedo(color, isSRGB); + } + } + } else if (key == "defaultFallthrough") { + auto value = materialJSON.value(key); + if (value.isBool()) { + material->setDefaultFallthrough(value.toBool()); + } + } else if (key == "procedural") { + auto value = materialJSON.value(key); + material->setProceduralData(QJsonDocument::fromVariant(value.toVariant()).toJson()); + } + } + networkMaterial = material; } - return std::pair>(name, material); + if (networkMaterial) { + networkMaterial->setModel(modelString); + } + + return std::pair>(name, networkMaterial); } NetworkMaterialResourcePointer MaterialCache::getMaterial(const QUrl& url) { diff --git a/libraries/material-networking/src/material-networking/MaterialCache.h b/libraries/procedural/src/procedural/ProceduralMaterialCache.h similarity index 98% rename from libraries/material-networking/src/material-networking/MaterialCache.h rename to libraries/procedural/src/procedural/ProceduralMaterialCache.h index 31bbd02198..bf4b5191c2 100644 --- a/libraries/material-networking/src/material-networking/MaterialCache.h +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.h @@ -14,7 +14,7 @@ #include #include -#include "TextureCache.h" +#include class NetworkMaterial : public graphics::Material { public: diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 5e8c6f4865..432e02fe10 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -19,10 +19,12 @@ ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _created(created) { // FIXME: support forward rendering for procedural skyboxes (needs haze calculation) - _procedural._vertexSource = gpu::Shader::createVertex(shader::graphics::vertex::skybox)->getSource(); + _procedural._vertexSource = shader::Source::get(shader::graphics::vertex::skybox); _procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox); - // Adjust the pipeline state for background using the stencil test + _procedural.setDoesFade(false); + + // Adjust the pipeline state for background using the stencil test // Must match PrepareStencil::STENCIL_BACKGROUND const int8_t STENCIL_BACKGROUND = 0; _procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_BACKGROUND, 0xFF, gpu::EQUAL, diff --git a/libraries/procedural/src/procedural/ShaderConstants.h b/libraries/procedural/src/procedural/ShaderConstants.h index cd0d997050..f1336b6479 100644 --- a/libraries/procedural/src/procedural/ShaderConstants.h +++ b/libraries/procedural/src/procedural/ShaderConstants.h @@ -14,17 +14,24 @@ #ifndef PROCEDURAL_SHADER_CONSTANTS_H #define PROCEDURAL_SHADER_CONSTANTS_H +#define PROCEDURAL_BUFFER_INPUTS 7 + #define PROCEDURAL_UNIFORM_CUSTOM 220 -#define PROCEDURAL_TEXTURE_CHANNEL0 0 -#define PROCEDURAL_TEXTURE_CHANNEL1 1 -#define PROCEDURAL_TEXTURE_CHANNEL2 2 -#define PROCEDURAL_TEXTURE_CHANNEL3 3 +#define PROCEDURAL_TEXTURE_CHANNEL0 2 +#define PROCEDURAL_TEXTURE_CHANNEL1 3 +#define PROCEDURAL_TEXTURE_CHANNEL2 4 +#define PROCEDURAL_TEXTURE_CHANNEL3 5 // & clusterMatrices, const std::vector& cauterizedClusterMatrices) { diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 87d8ce7ae9..f1fe5faa35 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -13,7 +13,7 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload { public: - CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform); + CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform, const uint64_t& created); // matrix palette skinning void updateClusterBuffer(const std::vector& clusterMatrices, diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 69710b2ed1..4c2c487193 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -67,7 +67,7 @@ void CauterizedModel::createRenderItemSet() { for (int shapeID = 0; shapeID < (int) shapes.size(); shapeID++) { const auto& shape = shapes[shapeID]; - _modelMeshRenderItems << std::make_shared(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform); + _modelMeshRenderItems << std::make_shared(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform, offset, _created); auto material = getNetworkModel()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 6e3fe6ebec..8476b490d8 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -11,15 +11,23 @@ #include "MeshPartPayload.h" +#include + #include #include #include #include "render-utils/ShaderConstants.h" +#include #include "DeferredLightingEffect.h" #include "RenderPipelines.h" +static const QString ENABLE_MATERIAL_PROCEDURAL_SHADERS_STRING { "HIFI_ENABLE_MATERIAL_PROCEDURAL_SHADERS" }; +static bool ENABLE_MATERIAL_PROCEDURAL_SHADERS = QProcessEnvironment::systemEnvironment().contains(ENABLE_MATERIAL_PROCEDURAL_SHADERS_STRING); + +bool MeshPartPayload::enableMaterialProceduralShaders = false; + using namespace render; namespace render { @@ -49,7 +57,9 @@ template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderAr } } -MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material) { +MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created) : + _created(created) +{ updateMeshPart(mesh, partIndex); addMaterial(graphics::MaterialLayer(material, 0)); } @@ -108,20 +118,30 @@ Item::Bound MeshPartPayload::getBound() const { } ShapeKey MeshPartPayload::getShapeKey() const { - graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); - ShapeKey::Builder builder; - builder.withMaterial(); + graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; + graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } - if (drawMaterialKey.isNormalMap()) { - builder.withTangents(); - } - if (drawMaterialKey.isLightMap()) { - builder.withLightMap(); + + if (material && material->isProcedural() && material->isReady()) { + builder.withOwnPipeline(); + } else { + builder.withMaterial(); + + if (drawMaterialKey.isNormalMap()) { + builder.withTangents(); + } + if (drawMaterialKey.isLightMap()) { + builder.withLightMap(); + } + if (drawMaterialKey.isUnlit()) { + builder.withUnlit(); + } } + return builder.build(); } @@ -157,9 +177,20 @@ void MeshPartPayload::render(RenderArgs* args) { //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); - // apply material properties - if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; + if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && + _drawMaterials.top().material->isReady()) { + auto procedural = std::static_pointer_cast(_drawMaterials.top().material); + auto& schema = _drawMaterials.getSchemaBuffer().get(); + glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); + outColor = procedural->getColor(outColor); + procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, + ProceduralProgramKey(outColor.a < 1.0f)); + batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); + } else { + // apply material properties + if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; + } } // Draw! @@ -200,7 +231,8 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren } -ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform) : +ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, + const Transform& transform, const Transform& offsetTransform, const uint64_t& created) : _meshIndex(meshIndex), _shapeID(shapeIndex) { @@ -237,6 +269,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in } #endif + _created = created; } void ModelMeshPartPayload::initCache(const ModelPointer& model) { @@ -335,43 +368,47 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr RenderPipelines::updateMultiMaterial(_drawMaterials); } + ShapeKey::Builder builder; + graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); - bool isTranslucent = drawMaterialKey.isTranslucent(); - bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents; - bool hasLightmap = drawMaterialKey.isLightMap(); - bool isUnlit = drawMaterialKey.isUnlit(); - - bool isDeformed = _isBlendShaped || _isSkinned; bool isWireframe = primitiveMode == PrimitiveMode::LINES; if (isWireframe) { - isTranslucent = hasTangents = hasLightmap = false; - } - - ShapeKey::Builder builder; - builder.withMaterial(); - - if (isTranslucent) { + builder.withWireframe(); + } else if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } - if (hasTangents) { - builder.withTangents(); - } - if (hasLightmap) { - builder.withLightMap(); - } - if (isUnlit) { - builder.withUnlit(); - } - if (isDeformed) { + + if (_isSkinned || (_isBlendShaped && _meshBlendshapeBuffer)) { builder.withDeformed(); + if (useDualQuaternionSkinning) { + builder.withDualQuatSkinned(); + } } - if (isWireframe) { - builder.withWireframe(); - } - if (isDeformed && useDualQuaternionSkinning) { - builder.withDualQuatSkinned(); + + if (material && material->isProcedural() && material->isReady()) { + builder.withOwnPipeline(); + } else { + bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents; + bool hasLightmap = drawMaterialKey.isLightMap(); + bool isUnlit = drawMaterialKey.isUnlit(); + + if (isWireframe) { + hasTangents = hasLightmap = false; + } + + builder.withMaterial(); + + if (hasTangents) { + builder.withTangents(); + } + if (hasLightmap) { + builder.withLightMap(); + } + if (isUnlit) { + builder.withUnlit(); + } } _shapeKey = builder.build(); @@ -417,9 +454,23 @@ void ModelMeshPartPayload::render(RenderArgs* args) { batch.setDrawcallUniform(drawcallInfo); } - // apply material properties - if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; + if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && + _drawMaterials.top().material->isReady()) { + if (!(enableMaterialProceduralShaders && ENABLE_MATERIAL_PROCEDURAL_SHADERS)) { + return; + } + auto procedural = std::static_pointer_cast(_drawMaterials.top().material); + auto& schema = _drawMaterials.getSchemaBuffer().get(); + glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); + outColor = procedural->getColor(outColor); + procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, + ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned())); + batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); + } else { + // apply material properties + if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; + } } // Draw! diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b207bd9403..4f04623916 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -27,7 +27,7 @@ class Model; class MeshPartPayload { public: MeshPartPayload() = default; - MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material); + MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created); virtual ~MeshPartPayload() = default; typedef render::Payload Payload; @@ -72,8 +72,11 @@ public: void addMaterial(graphics::MaterialLayer material); void removeMaterial(graphics::MaterialPointer material); + static bool enableMaterialProceduralShaders; + protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; + uint64_t _created; }; namespace render { @@ -85,7 +88,7 @@ namespace render { class ModelMeshPartPayload : public MeshPartPayload { public: - ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform); + ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform, const uint64_t& created); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 278376fe4a..116c3dbb19 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -50,7 +50,7 @@ int normalTypeVecTypeId = qRegisterMetaType>("QVector(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform); + _modelMeshRenderItems << std::make_shared(shared_from_this(), shape.mesh, shape.meshPart, shapeID, transform, offset, _created); auto material = getNetworkModel()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 0c04aca70c..eae6370cc0 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -99,7 +99,7 @@ public: static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; } - Model(QObject* parent = nullptr, SpatiallyNestable* spatiallyNestableOverride = nullptr); + Model(QObject* parent = nullptr, SpatiallyNestable* spatiallyNestableOverride = nullptr, uint64_t created = 0); virtual ~Model(); inline ModelPointer getThisPointer() const { @@ -518,6 +518,8 @@ protected: bool shouldInvalidatePayloadShapeKey(int meshIndex); + uint64_t _created; + private: float _loadingPriority { 0.0f }; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 518e43a8ec..2b0d197819 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -675,6 +675,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial case graphics::MaterialKey::METALLIC_VAL_BIT: case graphics::MaterialKey::GLOSSY_VAL_BIT: case graphics::MaterialKey::OPACITY_VAL_BIT: + case graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT: case graphics::MaterialKey::SCATTERING_VAL_BIT: case graphics::Material::TEXCOORDTRANSFORM0: case graphics::Material::TEXCOORDTRANSFORM1: diff --git a/libraries/render-utils/src/render-utils/simple_procedural.slp b/libraries/render-utils/src/render-utils/simple_procedural.slp index 1348d72a8d..219062d50c 100644 --- a/libraries/render-utils/src/render-utils/simple_procedural.slp +++ b/libraries/render-utils/src/render-utils/simple_procedural.slp @@ -1 +1 @@ -DEFINES translucent:f \ No newline at end of file +DEFINES translucent:f deformed:v/deformeddq:v \ No newline at end of file diff --git a/libraries/render-utils/src/simple_procedural.slv b/libraries/render-utils/src/simple_procedural.slv index 181afa50bd..a8d494f72d 100644 --- a/libraries/render-utils/src/simple_procedural.slv +++ b/libraries/render-utils/src/simple_procedural.slv @@ -17,6 +17,16 @@ <@include render-utils/ShaderConstants.h@> +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + <@include MeshDeformer.slh@> + <@if HIFI_USE_DEFORMED@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$> + <@else@> + <$declareMeshDeformer(1, _SCRIBE_NULL, 1, 1, 1)$> + <@endif@> + <$declareMeshDeformerActivation(1, 1)$> +<@endif@> + layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _positionMS; layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES; layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS; @@ -25,13 +35,23 @@ layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color; layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main(void) { - _color = color_sRGBAToLinear(inColor); - _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); - _positionMS = inPosition; - _normalMS = inNormal.xyz; + vec4 positionMS = inPosition; + vec3 normalMS = inNormal.xyz; + +<@if HIFI_USE_DEFORMED or HIFI_USE_DEFORMEDDQ@> + evalMeshDeformer(inPosition, positionMS, inNormal.xyz, normalMS, + meshDeformer_doSkinning(_drawCallInfo.y), inSkinClusterIndex, inSkinClusterWeight, + meshDeformer_doBlendshape(_drawCallInfo.y), gl_VertexID); +<@endif@> + + _positionMS = positionMS; + _normalMS = normalMS; TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyeAndClipPos(cam, obj, inPosition, _positionES, gl_Position)$> - <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> + <$transformModelToEyeAndClipPos(cam, obj, positionMS, _positionES, gl_Position)$> + <$transformModelToWorldDir(cam, obj, normalMS, _normalWS)$> + + _color = color_sRGBAToLinear(inColor); + _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); } \ No newline at end of file diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 82c408f386..0fefff1c4c 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -17,6 +17,12 @@ if (NOT ANDROID) endif () -link_hifi_libraries(shared networking octree shaders gpu procedural graphics material-networking model-networking ktx recording avatars fbx hfm entities controllers animation audio physics image midi) -# ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit +link_hifi_libraries(shared networking shaders material-networking model-networking recording avatars fbx entities controllers animation audio midi) include_hifi_library_headers(gl) +include_hifi_library_headers(hfm) +include_hifi_library_headers(gpu) +include_hifi_library_headers(ktx) +include_hifi_library_headers(image) +include_hifi_library_headers(graphics) +include_hifi_library_headers(octree) +include_hifi_library_headers(procedural) \ No newline at end of file diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index afff0a6b03..8335cb9adf 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -16,8 +16,6 @@ #include -#include - #include "ScriptEngineLogging.h" #include "ScriptEngine.h" diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index 7b36b815fb..90159f8ee6 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -11,129 +11,6 @@ #include "SceneScriptingInterface.h" -#include - -float SceneScripting::Location::getLongitude() const { - return _skyStage->getOriginLongitude(); -} - -float SceneScripting::Location::getLatitude() const { - return _skyStage->getOriginLatitude(); -} - -float SceneScripting::Location::getAltitude() const { - return _skyStage->getOriginSurfaceAltitude(); -} - -void SceneScripting::Location::setLongitude(float longitude) { - _skyStage->setOriginLongitude(longitude); -} - -void SceneScripting::Location::setLatitude(float latitude) { - _skyStage->setOriginLatitude(latitude); -} - -void SceneScripting::Location::setAltitude(float altitude) { - _skyStage->setOriginSurfaceAltitude(altitude); -} - -void SceneScripting::Time::setHour(float hour) { - _skyStage->setDayTime(hour); -} - -float SceneScripting::Time::getHour() const { - return _skyStage->getDayTime(); -} - -void SceneScripting::Time::setDay(int day) { - _skyStage->setYearTime(day); -} - -int SceneScripting::Time::getDay() const { - return _skyStage->getYearTime(); -} - -glm::vec3 SceneScripting::KeyLight::getColor() const { - return _skyStage->getSunColor(); -} - -void SceneScripting::KeyLight::setColor(const glm::vec3& color) { - _skyStage->setSunColor(color); -} - -float SceneScripting::KeyLight::getIntensity() const { - return _skyStage->getSunIntensity(); -} - -void SceneScripting::KeyLight::setIntensity(float intensity) { - _skyStage->setSunIntensity(intensity); -} - -float SceneScripting::KeyLight::getAmbientIntensity() const { - return _skyStage->getSunAmbientIntensity(); -} - -void SceneScripting::KeyLight::setAmbientIntensity(float intensity) { - _skyStage->setSunAmbientIntensity(intensity); -} - -void SceneScripting::KeyLight::setAmbientSphere(const gpu::SHPointer& sphere) { - _skyStage->setSunAmbientSphere(sphere); -} - -void SceneScripting::KeyLight::setAmbientMap(const gpu::TexturePointer& map) { - _skyStage->setSunAmbientMap(map); -} - - -glm::vec3 SceneScripting::KeyLight::getDirection() const { - return _skyStage->getSunDirection(); -} - -void SceneScripting::KeyLight::setDirection(const glm::vec3& direction) { - _skyStage->setSunDirection(direction); -} - -void SceneScripting::Stage::setOrientation(const glm::quat& orientation) const { - _skyStage->setOriginOrientation(orientation); -} - -void SceneScripting::Stage::setLocation(float longitude, float latitude, float altitude) { - _skyStage->setOriginLocation(longitude, latitude, altitude); -} - -void SceneScripting::Stage::setSunModelEnable(bool isEnabled) { - _skyStage->setSunModelEnable(isEnabled); -} - -bool SceneScripting::Stage::isSunModelEnabled() const { - return _skyStage->isSunModelEnabled(); -} - -void SceneScripting::Stage::setBackgroundMode(const QString& mode) { - if (mode == QString("inherit")) { - _skyStage->setBackgroundMode(graphics::SunSkyStage::NO_BACKGROUND); - } else if (mode == QString("skybox")) { - _skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_BOX); - } -} - -QString SceneScripting::Stage::getBackgroundMode() const { - switch (_skyStage->getBackgroundMode()) { - case graphics::SunSkyStage::NO_BACKGROUND: - return QString("inherit"); - case graphics::SunSkyStage::SKY_BOX: - return QString("skybox"); - default: - return QString("inherit"); - }; -} - -SceneScriptingInterface::SceneScriptingInterface() : _stage{ new SceneScripting::Stage{ _skyStage } } { - // Let's make sure the sunSkyStage is using a proceduralSkybox - _skyStage->setSkybox(graphics::SkyboxPointer(new ProceduralSkybox())); -} - void SceneScriptingInterface::setShouldRenderAvatars(bool shouldRenderAvatars) { if (shouldRenderAvatars != _shouldRenderAvatars) { _shouldRenderAvatars = shouldRenderAvatars; @@ -146,8 +23,4 @@ void SceneScriptingInterface::setShouldRenderEntities(bool shouldRenderEntities) _shouldRenderEntities = shouldRenderEntities; emit shouldRenderEntitiesChanged(_shouldRenderEntities); } -} - -graphics::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { - return _skyStage; -} +} \ No newline at end of file diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index fa67666676..ce205bdf3c 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -12,183 +12,8 @@ #ifndef hifi_SceneScriptingInterface_h #define hifi_SceneScriptingInterface_h -#include // QObject -#include // Dependency - -#include "graphics/Stage.h" - -// TODO: if QT moc ever supports nested classes, subclass these to the interface instead of namespacing -namespace SceneScripting { - - /**jsdoc - * Stage location. - * @typedef {object} Stage.Location - * @property {number} longitude - Longitude. - * @property {number} latitude - Latitude. - * @property {number} altitude - Altitude. - */ - class Location : public QObject { - Q_OBJECT - - public: - Location(graphics::SunSkyStagePointer skyStage) : _skyStage{ skyStage } {} - - Q_PROPERTY(float longitude READ getLongitude WRITE setLongitude) - Q_PROPERTY(float latitude READ getLatitude WRITE setLatitude) - Q_PROPERTY(float altitude READ getAltitude WRITE setAltitude) - - float getLongitude() const; - float getLatitude() const; - float getAltitude() const; - void setLongitude(float longitude); - void setLatitude(float latitude); - void setAltitude(float altitude); - - protected: - graphics::SunSkyStagePointer _skyStage; - }; - using LocationPointer = std::unique_ptr; - - /**jsdoc - * Stage time. - * @typedef {object} Stage.Time - * @property {number} hour - Hour. - * @property {number} day - Day. - */ - class Time : public QObject { - Q_OBJECT - - public: - Time(graphics::SunSkyStagePointer skyStage) : _skyStage{ skyStage } {} - - Q_PROPERTY(float hour READ getHour WRITE setHour) - Q_PROPERTY(int day READ getDay WRITE setDay) - - float getHour() const; - void setHour(float hour); - int getDay() const; - void setDay(int day); - - protected: - graphics::SunSkyStagePointer _skyStage; - }; - using TimePointer = std::unique_ptr