diff --git a/CMakeLists.txt b/CMakeLists.txt index fa85f13c24..8332db6151 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,8 +184,13 @@ if(OVERTE_WARNINGS_WHITELIST) endif() if(OVERTE_WARNINGS_AS_ERRORS) - set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} -Werror") - set(ENV{CFLAGS} "$ENV{CXXFLAGS} -Werror") + if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "" AND WIN32)) + set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} /WX") + set(ENV{CFLAGS} "$ENV{CXXFLAGS} /WX") + else() + set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} -Werror") + set(ENV{CFLAGS} "$ENV{CXXFLAGS} -Werror") + endif() endif() @@ -252,9 +257,6 @@ else() endif() set(SCREENSHARE 0) -if (WIN32) - set(SCREENSHARE 1) -endif() if (APPLE AND NOT CLIENT_ONLY) # Don't include Screenshare in OSX client-only builds. set(SCREENSHARE 1) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index c919d2a2d7..929cd68f7c 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -32,6 +32,10 @@ ScriptableAvatar::ScriptableAvatar(): _scriptEngine(newScriptEngine()) { _clientTraitsHandler.reset(new ClientTraitsHandler(this)); + static std::once_flag once; + std::call_once(once, [] { + qRegisterMetaType("HFMModel::Pointer"); + }); } QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) { @@ -52,6 +56,7 @@ void ScriptableAvatar::startAnimation(const QString& url, float fps, float prior _animation = DependencyManager::get()->getAnimation(url); _animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame, false); _maskedJoints = maskedJoints; + _isAnimationRigValid = false; } void ScriptableAvatar::stopAnimation() { @@ -89,11 +94,12 @@ QStringList ScriptableAvatar::getJointNames() const { } void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - _bind.reset(); - _animSkeleton.reset(); + _avatarAnimSkeleton.reset(); + _geometryResource.reset(); AvatarData::setSkeletonModelURL(skeletonModelURL); updateJointMappings(); + _isRigValid = false; } int ScriptableAvatar::sendAvatarDataPacket(bool sendAll) { @@ -137,65 +143,87 @@ static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, } void ScriptableAvatar::update(float deltatime) { + if (!_geometryResource && !_skeletonModelFilenameURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton. + _geometryResource = DependencyManager::get()->getGeometryResource(_skeletonModelFilenameURL); + } + // Run animation - if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) { - if (!_animSkeleton) { - _animSkeleton = std::make_shared(_bind->getHFMModel()); - } - float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps; - if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) { - while (currentFrame >= _animationDetails.lastFrame) { - currentFrame -= (_animationDetails.lastFrame - _animationDetails.firstFrame); + Q_ASSERT(QThread::currentThread() == thread()); + if (_animation && _animation->isLoaded()) { + Q_ASSERT(thread() == _animation->thread()); + auto frames = _animation->getFramesReference(); + if (frames.size() > 0 && _geometryResource && _geometryResource->isHFMModelLoaded()) { + if (!_isRigValid) { + _rig.reset(_geometryResource->getHFMModel()); + _isRigValid = true; } - _animationDetails.currentFrame = currentFrame; - - const QVector& modelJoints = _bind->getHFMModel().joints; - QStringList animationJointNames = _animation->getJointNames(); - - const int nJoints = modelJoints.size(); - if (_jointData.size() != nJoints) { - _jointData.resize(nJoints); + if (!_isAnimationRigValid) { + _animationRig.reset(_animation->getHFMModel()); + _isAnimationRigValid = true; } - - const int frameCount = _animation->getFrames().size(); - const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount); - const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount); - const float frameFraction = glm::fract(currentFrame); - std::vector poses = _animSkeleton->getRelativeDefaultPoses(); - - const float UNIT_SCALE = 0.01f; - - for (int i = 0; i < animationJointNames.size(); i++) { - const QString& name = animationJointNames[i]; - // As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than - // trusting the .fst (which is sometimes not updated to match changes to .fbx). - int mapping = _bind->getHFMModel().getJointIndex(name); - if (mapping != -1 && !_maskedJoints.contains(name)) { - - AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE); - AnimPose ceilPose = composeAnimPose(modelJoints[mapping], ceilFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE); - blend(1, &floorPose, &ceilPose, frameFraction, &poses[mapping]); - } + if (!_avatarAnimSkeleton) { + _avatarAnimSkeleton = std::make_shared(_geometryResource->getHFMModel()); } - - std::vector absPoses = poses; - _animSkeleton->convertRelativePosesToAbsolute(absPoses); - for (int i = 0; i < nJoints; i++) { - JointData& data = _jointData[i]; - AnimPose& absPose = absPoses[i]; - if (data.rotation != absPose.rot()) { - data.rotation = absPose.rot(); - data.rotationIsDefaultPose = false; + float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps; + if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) { + while (currentFrame >= _animationDetails.lastFrame) { + currentFrame -= (_animationDetails.lastFrame - _animationDetails.firstFrame); } - AnimPose& relPose = poses[i]; - if (data.translation != relPose.trans()) { - data.translation = relPose.trans(); - data.translationIsDefaultPose = false; - } - } + _animationDetails.currentFrame = currentFrame; - } else { - _animation.clear(); + const QVector& modelJoints = _geometryResource->getHFMModel().joints; + QStringList animationJointNames = _animation->getJointNames(); + + const int nJoints = modelJoints.size(); + if (_jointData.size() != nJoints) { + _jointData.resize(nJoints); + } + + const int frameCount = frames.size(); + const HFMAnimationFrame& floorFrame = frames.at((int)glm::floor(currentFrame) % frameCount); + const HFMAnimationFrame& ceilFrame = frames.at((int)glm::ceil(currentFrame) % frameCount); + const float frameFraction = glm::fract(currentFrame); + std::vector poses = _avatarAnimSkeleton->getRelativeDefaultPoses(); + + // TODO: this needs more testing, it's possible that we need not only scale but also rotation and translation + // According to tests with unmatching avatar and animation armatures, sometimes bones are not rotated correctly. + // Matching armatures already work very well now. + const float UNIT_SCALE = _animationRig.GetScaleFactorGeometryToUnscaledRig() / _rig.GetScaleFactorGeometryToUnscaledRig(); + + for (int i = 0; i < animationJointNames.size(); i++) { + const QString& name = animationJointNames[i]; + // As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than + // trusting the .fst (which is sometimes not updated to match changes to .fbx). + int mapping = _geometryResource->getHFMModel().getJointIndex(name); + if (mapping != -1 && !_maskedJoints.contains(name)) { + AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], + floorFrame.translations[i] * UNIT_SCALE); + AnimPose ceilPose = composeAnimPose(modelJoints[mapping], ceilFrame.rotations[i], + ceilFrame.translations[i] * UNIT_SCALE); + blend(1, &floorPose, &ceilPose, frameFraction, &poses[mapping]); + } + } + + std::vector absPoses = poses; + Q_ASSERT(_avatarAnimSkeleton != nullptr); + _avatarAnimSkeleton->convertRelativePosesToAbsolute(absPoses); + for (int i = 0; i < nJoints; i++) { + JointData& data = _jointData[i]; + AnimPose& absPose = absPoses[i]; + if (data.rotation != absPose.rot()) { + data.rotation = absPose.rot(); + data.rotationIsDefaultPose = false; + } + AnimPose& relPose = poses[i]; + if (data.translation != relPose.trans()) { + data.translation = relPose.trans(); + data.translationIsDefaultPose = false; + } + } + + } else { + _animation.clear(); + } } } @@ -245,6 +273,7 @@ void ScriptableAvatar::setJointMappingsFromNetworkReply() { networkReply->deleteLater(); return; } + // TODO: this works only with .fst files currently, not directly with FBX and GLB models { QWriteLocker writeLock(&_jointDataLock); QByteArray line; @@ -253,7 +282,7 @@ void ScriptableAvatar::setJointMappingsFromNetworkReply() { if (line.startsWith("filename")) { int filenameIndex = line.indexOf('=') + 1; if (filenameIndex > 0) { - _skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed())); + _skeletonModelFilenameURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed())); } } if (!line.startsWith("jointIndex")) { diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 703a0a9f64..192de31a26 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -19,6 +19,8 @@ #include #include #include +#include "model-networking/ModelCache.h" +#include "Rig.h" /*@jsdoc * The Avatar API is used to manipulate scriptable avatars on the domain. This API is a subset of the @@ -217,11 +219,15 @@ private: AnimationPointer _animation; AnimationDetails _animationDetails; QStringList _maskedJoints; - AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies - std::shared_ptr _animSkeleton; + GeometryResource::Pointer _geometryResource; + Rig _rig; + bool _isRigValid{false}; + Rig _animationRig; + bool _isAnimationRigValid{false}; + std::shared_ptr _avatarAnimSkeleton; QHash _fstJointIndices; ///< 1-based, since zero is returned for missing keys QStringList _fstJointNames; ///< in order of depth-first traversal - QUrl _skeletonFBXURL; + QUrl _skeletonModelFilenameURL; // This contains URL from filename field in fst file mutable ScriptEnginePointer _scriptEngine; std::map _entities; diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index 492ec265d4..0115961d02 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -27,7 +27,7 @@ Item { width: parent.width property string title: "Controls" - property var openVRDevices: ["HTC Vive", "Valve Index", "Valve HMD", "Valve", "WindowsMR"] + property var openVRDevices: ["HTC Vive", "Valve Index", "Valve HMD", "Valve", "WindowsMR", "Oculus"] HifiConstants { id: hifi } diff --git a/launchers/qt/CMakeLists.txt b/launchers/qt/CMakeLists.txt index 12cf7f08d4..0e5ddd6990 100644 --- a/launchers/qt/CMakeLists.txt +++ b/launchers/qt/CMakeLists.txt @@ -281,7 +281,7 @@ if (APPLE) set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME}) - set(DMG_SUBFOLDER_NAME "Vircadia") + set(DMG_SUBFOLDER_NAME "Overte") set(ESCAPED_DMG_SUBFOLDER_NAME "") set(DMG_SUBFOLDER_ICON "${CMAKE_SOURCE_DIR}/cmake/installer/install-folder.rsrc") diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index b086f42d72..49962decc4 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -337,21 +337,26 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { } // Draw! - DependencyManager::get()->renderSphere(batch); + const uint32_t compactColor = 0xFFFFFFFF; + _colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); + DependencyManager::get()->renderShape(batch, GeometryCache::Shape::Sphere, _colorBuffer); } else { auto proceduralDrawMaterial = std::static_pointer_cast(drawMaterial); glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity()); outColor = proceduralDrawMaterial->getColor(outColor); proceduralDrawMaterial->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); + + const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor)); + _colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { - DependencyManager::get()->renderWireSphere(batch, outColor); + DependencyManager::get()->renderWireShape(batch, GeometryCache::Shape::Sphere, _colorBuffer); } else { - DependencyManager::get()->renderSphere(batch, outColor); + DependencyManager::get()->renderShape(batch, GeometryCache::Shape::Sphere, _colorBuffer); } } - args->_details._trianglesRendered += (int)DependencyManager::get()->getSphereTriangleCount(); + args->_details._trianglesRendered += (int)DependencyManager::get()->getShapeTriangleCount(GeometryCache::Shape::Sphere); } void MaterialEntityRenderer::setCurrentMaterialName(const std::string& currentMaterialName) { diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index ad1f9771a5..efded3aab3 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -67,6 +67,7 @@ private: std::shared_ptr _appliedMaterial; std::string _currentMaterialName; + gpu::BufferPointer _colorBuffer { std::make_shared() }; }; } } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 1355885625..02491105f5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -131,10 +131,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); }); + const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor)); + _colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); if (wireframe) { - geometryCache->renderWireShape(batch, geometryShape, outColor); + geometryCache->renderWireShape(batch, geometryShape, _colorBuffer); } else { - geometryCache->renderShape(batch, geometryShape, outColor); + geometryCache->renderShape(batch, geometryShape, _colorBuffer); } } else if (pipelineType == Pipeline::SIMPLE) { // FIXME, support instanced multi-shape rendering using multidraw indirect @@ -149,10 +151,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); } } else { + const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor)); + _colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); if (wireframe) { - geometryCache->renderWireShape(batch, geometryShape, outColor); + geometryCache->renderWireShape(batch, geometryShape, _colorBuffer); } else { - geometryCache->renderShape(batch, geometryShape, outColor); + geometryCache->renderShape(batch, geometryShape, _colorBuffer); } } } else { @@ -160,7 +164,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { args->_details._materialSwitches++; } - geometryCache->renderShape(batch, geometryShape); + const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor)); + _colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); + geometryCache->renderShape(batch, geometryShape, _colorBuffer); } const auto triCount = geometryCache->getShapeTriangleCount(geometryShape); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 686014f4de..fd7bd4795b 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -42,6 +42,8 @@ private: std::shared_ptr _material { std::make_shared() }; glm::vec3 _color { NAN }; float _alpha { NAN }; + + gpu::BufferPointer _colorBuffer { std::make_shared() }; }; } } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index af39458f17..47861d4f80 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -100,8 +100,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_glUniformMatrix3fv), (&::gpu::gl::GLBackend::do_glUniformMatrix4fv), - (&::gpu::gl::GLBackend::do_glColor4f), - (&::gpu::gl::GLBackend::do_pushProfileRange), (&::gpu::gl::GLBackend::do_popProfileRange), }; @@ -838,22 +836,6 @@ void GLBackend::do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) { (void)CHECK_GL_ERROR(); } -void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) { - - glm::vec4 newColor( - batch._params[paramOffset + 3]._float, - batch._params[paramOffset + 2]._float, - batch._params[paramOffset + 1]._float, - batch._params[paramOffset + 0]._float); - - if (_input._colorAttribute != newColor) { - _input._colorAttribute = newColor; - glVertexAttrib4fv(gpu::Stream::COLOR, &_input._colorAttribute.r); - _input._hasColorAttribute = true; - } - (void)CHECK_GL_ERROR(); -} - void GLBackend::releaseBuffer(GLuint id, Size size) const { Lock lock(_trashMutex); _currentFrameTrash.buffersTrash.push_back({ id, size }); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 2947649ce7..73e99ce1ac 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -241,8 +241,6 @@ public: virtual void do_glUniformMatrix3fv(const Batch& batch, size_t paramOffset) final; virtual void do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) final; - virtual void do_glColor4f(const Batch& batch, size_t paramOffset) final; - // The State setters called by the GLState::Commands when a new state is assigned virtual void do_setStateFillMode(int32 mode) final; virtual void do_setStateCullMode(int32 mode) final; @@ -350,8 +348,6 @@ protected: struct InputStageState { bool _invalidFormat { true }; bool _lastUpdateStereoState { false }; - bool _hasColorAttribute { false }; - bool _hadColorAttribute { false }; FormatReference _format { GPU_REFERENCE_INIT_VALUE }; std::string _formatKey; @@ -368,8 +364,6 @@ protected: std::array _bufferStrides; std::array _bufferVBOs; - glm::vec4 _colorAttribute { 1.0f }; - BufferReference _indexBuffer; Offset _indexBufferOffset { 0 }; Type _indexBufferType { UINT32 }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp index 4efd5f9941..e5b0ead027 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp @@ -103,9 +103,6 @@ void GLBackend::resetInputStage() { reset(_input._format); _input._formatKey.clear(); _input._invalidFormat = false; - _input._hasColorAttribute = false; - _input._hadColorAttribute = false; - _input._colorAttribute = vec4(1.0f); _input._attributeActivation.reset(); for (uint32_t i = 0; i < _input._buffers.size(); i++) { @@ -163,8 +160,6 @@ void GLBackend::updateInput() { #endif _input._lastUpdateStereoState = isStereoNow; - bool hasColorAttribute = _input._hasColorAttribute; - if (_input._invalidFormat) { InputStageState::ActivationCache newActivation; @@ -194,8 +189,6 @@ void GLBackend::updateInput() { GLenum perLocationSize = attrib._element.getLocationSize(); - hasColorAttribute |= slot == Stream::COLOR; - for (GLuint locNum = 0; locNum < locationCount; ++locNum) { GLuint attriNum = (GLuint)(slot + locNum); newActivation.set(attriNum); @@ -226,12 +219,6 @@ void GLBackend::updateInput() { glVertexBindingDivisor(bufferChannelNum, frequency); #endif } - - if (!hasColorAttribute && _input._hadColorAttribute) { - // The previous input stage had a color attribute but this one doesn't, so reset the color to pure white. - _input._colorAttribute = glm::vec4(1.0f); - glVertexAttrib4fv(Stream::COLOR, &_input._colorAttribute.r); - } } // Manage Activation what was and what is expected now @@ -253,9 +240,6 @@ void GLBackend::updateInput() { _stats._ISNumFormatChanges++; } - _input._hadColorAttribute = hasColorAttribute; - _input._hasColorAttribute = false; - if (_input._invalidBuffers.any()) { auto vbo = _input._bufferVBOs.data(); auto offset = _input._bufferOffsets.data(); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp index 188b4a1084..bdb37f6319 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp @@ -33,8 +33,6 @@ void GL41Backend::updateInput() { #endif _input._lastUpdateStereoState = isStereoNow; - bool hasColorAttribute = _input._hasColorAttribute; - if (_input._invalidFormat || _input._invalidBuffers.any()) { auto format = acquire(_input._format); @@ -110,8 +108,6 @@ void GL41Backend::updateInput() { uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]); GLboolean isNormalized = attrib._element.isNormalized(); - hasColorAttribute |= slot == Stream::COLOR; - for (size_t locNum = 0; locNum < locationCount; ++locNum) { if (attrib._element.isInteger()) { glVertexAttribIPointer(slot + (GLuint)locNum, count, type, stride, @@ -131,17 +127,8 @@ void GL41Backend::updateInput() { } } } - - if (!hasColorAttribute && _input._hadColorAttribute) { - // The previous input stage had a color attribute but this one doesn't, so reset the color to pure white. - _input._colorAttribute = glm::vec4(1.0f); - glVertexAttrib4fv(Stream::COLOR, &_input._colorAttribute.r); - } } // everything format related should be in sync now _input._invalidFormat = false; } - - _input._hadColorAttribute = hasColorAttribute; - _input._hasColorAttribute = false; } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp index 8add4a9296..7513ff7caf 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp @@ -35,8 +35,6 @@ void GL45Backend::updateInput() { #endif _input._lastUpdateStereoState = isStereoNow; - bool hasColorAttribute = _input._hasColorAttribute; - if (_input._invalidFormat) { InputStageState::ActivationCache newActivation; @@ -66,8 +64,6 @@ void GL45Backend::updateInput() { GLenum perLocationSize = attrib._element.getLocationSize(); - hasColorAttribute |= slot == Stream::COLOR; - for (GLuint locNum = 0; locNum < locationCount; ++locNum) { GLuint attriNum = (GLuint)(slot + locNum); newActivation.set(attriNum); @@ -98,12 +94,6 @@ void GL45Backend::updateInput() { glVertexBindingDivisor(bufferChannelNum, frequency); #endif } - - if (!hasColorAttribute && _input._hadColorAttribute) { - // The previous input stage had a color attribute but this one doesn't, so reset the color to pure white. - _input._colorAttribute = glm::vec4(1.0f); - glVertexAttrib4fv(Stream::COLOR, &_input._colorAttribute.r); - } } // Manage Activation what was and what is expected now @@ -125,9 +115,6 @@ void GL45Backend::updateInput() { _stats._ISNumFormatChanges++; } - _input._hadColorAttribute = hasColorAttribute; - _input._hasColorAttribute = false; - if (_input._invalidBuffers.any()) { auto vbo = _input._bufferVBOs.data(); auto offset = _input._bufferOffsets.data(); diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index e6217cc600..3654dfca5d 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -687,15 +687,6 @@ void Batch::_glUniformMatrix4fv(int32 location, int count, uint8 transpose, cons _params.emplace_back(location); } -void Batch::_glColor4f(float red, float green, float blue, float alpha) { - ADD_COMMAND(glColor4f); - - _params.emplace_back(alpha); - _params.emplace_back(blue); - _params.emplace_back(green); - _params.emplace_back(red); -} - void Batch::finishFrame(BufferUpdates& updates) { PROFILE_RANGE(render_gpu, __FUNCTION__); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 0a438ea148..be04f08e41 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -287,8 +287,6 @@ public: _glUniformMatrix3fv(location, 1, false, glm::value_ptr(v)); } - void _glColor4f(float red, float green, float blue, float alpha); - // Maybe useful but shoudln't be public. Please convince me otherwise // Well porting to gles i need it... void runLambda(std::function f); @@ -363,8 +361,6 @@ public: COMMAND_glUniformMatrix3fv, COMMAND_glUniformMatrix4fv, - COMMAND_glColor4f, - COMMAND_pushProfileRange, COMMAND_popProfileRange, diff --git a/libraries/gpu/src/gpu/FrameIOKeys.h b/libraries/gpu/src/gpu/FrameIOKeys.h index 1a98d0decd..4cb7c6085d 100644 --- a/libraries/gpu/src/gpu/FrameIOKeys.h +++ b/libraries/gpu/src/gpu/FrameIOKeys.h @@ -201,8 +201,6 @@ constexpr const char* COMMAND_NAMES[] = { "glUniformMatrix3fv", "glUniformMatrix4fv", - "glColor4f", - "pushProfileRange", "popProfileRange", }; diff --git a/libraries/graphics/src/graphics/Geometry.cpp b/libraries/graphics/src/graphics/Geometry.cpp index 0fb2a0eb51..3984863f1c 100644 --- a/libraries/graphics/src/graphics/Geometry.cpp +++ b/libraries/graphics/src/graphics/Geometry.cpp @@ -19,6 +19,8 @@ Mesh::Mesh() : _vertexBuffer(gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)), _indexBuffer(gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::INDEX)), _partBuffer(gpu::Element(gpu::VEC4, gpu::UINT32, gpu::PART)) { + const uint32_t compactColor = 0xFFFFFFFF; + _colorBuffer->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); } Mesh::Mesh(const Mesh& mesh) : @@ -26,7 +28,8 @@ Mesh::Mesh(const Mesh& mesh) : _vertexBuffer(mesh._vertexBuffer), _attributeBuffers(mesh._attributeBuffers), _indexBuffer(mesh._indexBuffer), - _partBuffer(mesh._partBuffer) { + _partBuffer(mesh._partBuffer), + _colorBuffer(mesh._colorBuffer) { } Mesh::~Mesh() { @@ -39,6 +42,13 @@ void Mesh::setVertexFormatAndStream(const gpu::Stream::FormatPointer& vf, const auto attrib = _vertexFormat->getAttribute(gpu::Stream::POSITION); _vertexBuffer = BufferView(vbs->getBuffers()[attrib._channel], vbs->getOffsets()[attrib._channel], vbs->getBuffers()[attrib._channel]->getSize(), (gpu::uint16) vbs->getStrides()[attrib._channel], attrib._element); + + // We require meshes to have a color attribute. If they don't, we default to white. + if (!_vertexFormat->hasAttribute(gpu::Stream::COLOR)) { + int channelNum = _vertexStream.getNumBuffers(); + _vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); + _vertexStream.addBuffer(_colorBuffer, 0, _vertexFormat->getChannels().at(channelNum)._stride); + } } void Mesh::setVertexBuffer(const BufferView& buffer) { @@ -98,6 +108,12 @@ void Mesh::evalVertexStream() { _vertexStream.addBuffer(view._buffer, view._offset, stride); channelNum++; } + + // We require meshes to have a color attribute. If they don't, we default to white. + if (!_vertexFormat->hasAttribute(gpu::Stream::COLOR)) { + _vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); + _vertexStream.addBuffer(_colorBuffer, 0, _vertexFormat->getChannels().at(channelNum)._stride); + } } void Mesh::setIndexBuffer(const BufferView& buffer) { diff --git a/libraries/graphics/src/graphics/Geometry.h b/libraries/graphics/src/graphics/Geometry.h index fe1981c0e9..dcaeaad271 100644 --- a/libraries/graphics/src/graphics/Geometry.h +++ b/libraries/graphics/src/graphics/Geometry.h @@ -15,6 +15,7 @@ #include +#include #include #include @@ -28,7 +29,6 @@ typedef glm::vec3 Vec3; class Mesh; using MeshPointer = std::shared_ptr< Mesh >; - class Mesh { public: const static Index PRIMITIVE_RESTART_INDEX = -1; @@ -142,6 +142,8 @@ public: std::string modelName; std::string displayName; + gpu::BufferPointer getColorBuffer() const { return _colorBuffer; } + protected: gpu::Stream::FormatPointer _vertexFormat; @@ -154,6 +156,8 @@ protected: BufferView _partBuffer; + gpu::BufferPointer _colorBuffer { std::make_shared() }; + void evalVertexFormat(); void evalVertexStream(); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 738c61874f..a488098b1b 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -355,8 +355,12 @@ void GeometryResource::deleter() { void GeometryResource::setTextures() { if (_hfmModel) { - for (const HFMMaterial& material : _hfmModel->materials) { - _materials.push_back(std::make_shared(material, _textureBaseURL)); + if (DependencyManager::get()) { + for (const HFMMaterial& material : _hfmModel->materials) { + _materials.push_back(std::make_shared(material, _textureBaseURL)); + } + } else { + qDebug() << "GeometryResource::setTextures: TextureCache dependency not available, skipping textures"; } } } diff --git a/libraries/model-serializers/src/GLTFSerializer.cpp b/libraries/model-serializers/src/GLTFSerializer.cpp index 73e2bf965c..1c6076809f 100644 --- a/libraries/model-serializers/src/GLTFSerializer.cpp +++ b/libraries/model-serializers/src/GLTFSerializer.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include #include #include @@ -460,6 +462,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& // Increment the triangle indices by the current mesh vertex count so each mesh part can all reference the same buffers within the mesh int prevMeshVerticesCount = mesh.vertices.count(); + // For each vertex (stride is WEIGHTS_PER_VERTEX), it contains index of the cluster that given weight belongs to. QVector clusterJoints; QVector clusterWeights; @@ -940,18 +943,17 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& } else { mesh.clusterWeights[prevMeshClusterWeightCount + j] = (uint16_t)((float)(UINT16_MAX) + ALMOST_HALF); } - for (int clusterIndex = 0; clusterIndex < mesh.clusters.size() - 1; ++clusterIndex) { + for (int k = j; k < j + WEIGHTS_PER_VERTEX; ++k) { + int clusterIndex = mesh.clusterIndices[prevMeshClusterIndexCount + k]; ShapeVertices& points = hfmModel.shapeVertices.at(clusterIndex); glm::vec3 globalMeshScale = extractScale(globalTransforms[nodeIndex]); const glm::mat4 meshToJoint = glm::scale(glm::mat4(), globalMeshScale) * jointInverseBindTransforms[clusterIndex]; - // TODO: The entire clustering is probably broken and detailed collision shapes fail to generate due to it. const uint16_t EXPANSION_WEIGHT_THRESHOLD = UINT16_MAX/4; // Equivalent of 0.25f? - if (mesh.clusterWeights[j] >= EXPANSION_WEIGHT_THRESHOLD) { - // TODO: fix transformed vertices being pushed back - auto& vertex = mesh.vertices[i]; - const glm::mat4 vertexTransform = meshToJoint * (glm::translate(glm::mat4(), vertex)); - glm::vec3 transformedVertex = hfmModel.joints[clusterIndex].translation * (extractTranslation(vertexTransform)); + if (mesh.clusterWeights[prevMeshClusterWeightCount + k] >= EXPANSION_WEIGHT_THRESHOLD) { + auto& vertex = mesh.vertices[prevMeshVerticesCount + i]; + const glm::mat4 vertexTransform = meshToJoint * glm::translate(vertex); + glm::vec3 transformedVertex = extractTranslation(vertexTransform); points.push_back(transformedVertex); } } diff --git a/libraries/networking/src/FingerprintUtils.cpp b/libraries/networking/src/FingerprintUtils.cpp index cab8cde832..5bb530d332 100644 --- a/libraries/networking/src/FingerprintUtils.cpp +++ b/libraries/networking/src/FingerprintUtils.cpp @@ -42,7 +42,7 @@ static const int HASH_ITERATIONS = 65535; // Salt string for the hardware ID, makes our IDs unique to our project. // Changing this results in different hardware IDs being computed. -static const QByteArray HASH_SALT{"Vircadia"}; +static const QByteArray HASH_SALT{"Overte"}; static const QString FALLBACK_FINGERPRINT_KEY = "fallbackFingerprint"; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 4beeb5b22f..25cb1404f0 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -587,7 +587,7 @@ void CharacterController::setLocalBoundingBox(const glm::vec3& minCorner, const } // it's ok to change offset immediately -- there are no thread safety issues here - _shapeLocalOffset = minCorner + 0.5f * scale; + _shapeLocalOffset = glm::vec3((minCorner + 0.5f * scale).x, (minCorner + 0.5f * scale).y, -(minCorner + 0.5f * scale).z); if (_rigidBody) { // update CCD with new _radius diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp index 02ec234266..f1dc8eedd4 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp @@ -865,7 +865,13 @@ graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl } const auto url = getTextureUrl(baseUrl, hfmTexture); - const auto texture = DependencyManager::get()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels, hfmTexture.sourceChannel); + auto textureCache = DependencyManager::get(); + NetworkTexturePointer texture; + if (textureCache) { + texture = textureCache->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels, hfmTexture.sourceChannel); + } else { + qDebug() << "GeometryResource::setTextures: TextureCache dependency not available, skipping textures"; + } _textures[channel] = Texture { hfmTexture.name, texture }; auto map = std::make_shared(); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 4ac097e31d..4d4f9c0680 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -99,14 +99,9 @@ static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element TEXCOORD0_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV }; static const gpu::Element TANGENT_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; -static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW }; static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; -static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; -static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT; static gpu::Stream::FormatPointer WIRE_STREAM_FORMAT; -static gpu::Stream::FormatPointer INSTANCED_WIRE_STREAM_FORMAT; -static gpu::Stream::FormatPointer INSTANCED_WIRE_FADE_STREAM_FORMAT; static const uint SHAPE_VERTEX_STRIDE = sizeof(GeometryCache::ShapeVertex); // position, normal, texcoords, tangent static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, normal); @@ -259,14 +254,6 @@ size_t GeometryCache::getShapeTriangleCount(Shape shape) { return _shapes[shape]._indicesView.getNumElements() / VERTICES_PER_TRIANGLE; } -size_t GeometryCache::getSphereTriangleCount() { - return getShapeTriangleCount(Sphere); -} - -size_t GeometryCache::getCubeTriangleCount() { - return getShapeTriangleCount(Cube); -} - using IndexPair = uint64_t; using IndexPairs = std::unordered_set; @@ -647,83 +634,24 @@ gpu::Stream::FormatPointer& getSolidStreamFormat() { SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); + SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return SOLID_STREAM_FORMAT; } -gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { - if (!INSTANCED_SOLID_STREAM_FORMAT) { - INSTANCED_SOLID_STREAM_FORMAT = std::make_shared(); // 1 for everyone - INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); - INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); - INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); - INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); - INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - } - return INSTANCED_SOLID_STREAM_FORMAT; -} - -gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { - if (!INSTANCED_SOLID_FADE_STREAM_FORMAT) { - INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared(); // 1 for everyone - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - } - return INSTANCED_SOLID_FADE_STREAM_FORMAT; -} - gpu::Stream::FormatPointer& getWireStreamFormat() { if (!WIRE_STREAM_FORMAT) { WIRE_STREAM_FORMAT = std::make_shared(); // 1 for everyone WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); + WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return WIRE_STREAM_FORMAT; } -gpu::Stream::FormatPointer& getInstancedWireStreamFormat() { - if (!INSTANCED_WIRE_STREAM_FORMAT) { - INSTANCED_WIRE_STREAM_FORMAT = std::make_shared(); // 1 for everyone - INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); - INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); - INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - } - return INSTANCED_WIRE_STREAM_FORMAT; -} - -gpu::Stream::FormatPointer& getInstancedWireFadeStreamFormat() { - if (!INSTANCED_WIRE_FADE_STREAM_FORMAT) { - INSTANCED_WIRE_FADE_STREAM_FORMAT = std::make_shared(); // 1 for everyone - INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); - INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); - INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); - } - return INSTANCED_WIRE_FADE_STREAM_FORMAT; -} - -QHash GeometryCache::_simplePrograms; - -gpu::ShaderPointer GeometryCache::_simpleShader; -gpu::ShaderPointer GeometryCache::_transparentShader; -gpu::ShaderPointer GeometryCache::_unlitShader; -gpu::ShaderPointer GeometryCache::_simpleFadeShader; -gpu::ShaderPointer GeometryCache::_unlitFadeShader; -gpu::ShaderPointer GeometryCache::_forwardSimpleShader; -gpu::ShaderPointer GeometryCache::_forwardTransparentShader; -gpu::ShaderPointer GeometryCache::_forwardUnlitShader; -gpu::ShaderPointer GeometryCache::_forwardSimpleFadeShader; -gpu::ShaderPointer GeometryCache::_forwardUnlitFadeShader; - +std::map, gpu::ShaderPointer> GeometryCache::_shapeShaders; std::map, render::ShapePipelinePointer> GeometryCache::_shapePipelines; +QHash GeometryCache::_simplePrograms; GeometryCache::GeometryCache() : _nextID(0) { @@ -809,103 +737,35 @@ render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured ); } -void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) { - batch.setInputFormat(getSolidStreamFormat()); - _shapes[shape].draw(batch); -} - -void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) { - batch.setInputFormat(getWireStreamFormat()); - _shapes[shape].drawWire(batch); -} - -void GeometryCache::renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { - batch.setInputFormat(getSolidStreamFormat()); - batch._glColor4f(color.r, color.g, color.b, color.a); - _shapes[shape].draw(batch); -} - -void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { - batch.setInputFormat(getWireStreamFormat()); - batch._glColor4f(color.r, color.g, color.b, color.a); - _shapes[shape].drawWire(batch); -} - -void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { +void setupColorInputBuffer(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); } +void GeometryCache::renderShape(gpu::Batch& batch, Shape shape, gpu::BufferPointer& colorBuffer) { + batch.setInputFormat(getSolidStreamFormat()); + setupColorInputBuffer(batch, colorBuffer); + _shapes[shape].draw(batch); +} + +void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, gpu::BufferPointer& colorBuffer) { + batch.setInputFormat(getWireStreamFormat()); + setupColorInputBuffer(batch, colorBuffer); + _shapes[shape].drawWire(batch); +} + void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { - batch.setInputFormat(getInstancedSolidStreamFormat()); - setupBatchInstance(batch, colorBuffer); + batch.setInputFormat(getSolidStreamFormat()); + setupColorInputBuffer(batch, colorBuffer); _shapes[shape].drawInstances(batch, count); } void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { - batch.setInputFormat(getInstancedWireStreamFormat()); - setupBatchInstance(batch, colorBuffer); + batch.setInputFormat(getWireStreamFormat()); + setupColorInputBuffer(batch, colorBuffer); _shapes[shape].drawWireInstances(batch, count); } -void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, - gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) { - gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); - gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT); - gpu::BufferView texCoord3View(fadeBuffer2, TEXCOORD4_ELEMENT); - gpu::BufferView texCoord4View(fadeBuffer3, TEXCOORD4_ELEMENT); - batch.setInputBuffer(gpu::Stream::COLOR, colorView); - batch.setInputBuffer(gpu::Stream::TEXCOORD2, texCoord2View); - batch.setInputBuffer(gpu::Stream::TEXCOORD3, texCoord3View); - batch.setInputBuffer(gpu::Stream::TEXCOORD4, texCoord4View); -} - -void GeometryCache::renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, - gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { - batch.setInputFormat(getInstancedSolidFadeStreamFormat()); - setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); - _shapes[shape].drawInstances(batch, count); -} - -void GeometryCache::renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, - gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { - batch.setInputFormat(getInstancedWireFadeStreamFormat()); - setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); - _shapes[shape].drawWireInstances(batch, count); -} - -void GeometryCache::renderCube(gpu::Batch& batch) { - renderShape(batch, Cube); -} - -void GeometryCache::renderWireCube(gpu::Batch& batch) { - renderWireShape(batch, Cube); -} - -void GeometryCache::renderCube(gpu::Batch& batch, const glm::vec4& color) { - renderShape(batch, Cube, color); -} - -void GeometryCache::renderWireCube(gpu::Batch& batch, const glm::vec4& color) { - renderWireShape(batch, Cube, color); -} - -void GeometryCache::renderSphere(gpu::Batch& batch) { - renderShape(batch, Sphere); -} - -void GeometryCache::renderWireSphere(gpu::Batch& batch) { - renderWireShape(batch, Sphere); -} - -void GeometryCache::renderSphere(gpu::Batch& batch, const glm::vec4& color) { - renderShape(batch, Sphere, color); -} - -void GeometryCache::renderWireSphere(gpu::Batch& batch, const glm::vec4& color) { - renderWireShape(batch, Sphere, color); -} - void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, int majorRows, int majorCols, float majorEdge, int minorRows, int minorCols, float minorEdge, const glm::vec4& color, bool forward, int id) { @@ -963,33 +823,30 @@ void GeometryCache::updateVertices(int id, const QVector& points, con #endif // def WANT_DEBUG } - const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals - const int NUM_POS_COORDS = 2; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); + const int FLOATS_PER_VERTEX = 2; // vertices details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); auto stream = std::make_shared(); details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); - // TODO: circle3D overlays use this to define their vertices, so they need tex coords - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - - details.vertices = points.size(); - details.vertexSize = FLOATS_PER_VERTEX; + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::POSITION)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::NORMAL)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::COLOR)._stride); float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX]; float* vertex = vertexData; @@ -997,7 +854,6 @@ void GeometryCache::updateVertices(int id, const QVector& points, con int* colorData = new int[details.vertices]; int* colorDataAt = colorData; - const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); auto pointCount = points.size(); auto colorCount = colors.size(); int compactColor = 0; @@ -1005,19 +861,16 @@ void GeometryCache::updateVertices(int id, const QVector& points, con const auto& point = points[i]; *(vertex++) = point.x; *(vertex++) = point.y; - *(vertex++) = NORMAL.x; - *(vertex++) = NORMAL.y; - *(vertex++) = NORMAL.z; if (i < colorCount) { const auto& color = colors[i]; - compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); + compactColor = GeometryCache::toCompactColor(color); } *(colorDataAt++) = compactColor; } + details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData); + const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData); delete[] vertexData; delete[] colorData; @@ -1040,32 +893,30 @@ void GeometryCache::updateVertices(int id, const QVector& points, con #endif // def WANT_DEBUG } - const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals - const int NUM_POS_COORDS = 3; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); + const int FLOATS_PER_VERTEX = 3; // vertices details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); auto stream = std::make_shared(); details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - - details.vertices = points.size(); - details.vertexSize = FLOATS_PER_VERTEX; + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::POSITION)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::NORMAL)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::COLOR)._stride); // Default to white int compactColor = 0xFFFFFFFF; @@ -1075,28 +926,23 @@ void GeometryCache::updateVertices(int id, const QVector& points, con int* colorData = new int[details.vertices]; int* colorDataAt = colorData; - const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); auto pointCount = points.size(); auto colorCount = colors.size(); for (auto i = 0; i < pointCount; i++) { const glm::vec3& point = points[i]; - if (i < colorCount) { - const glm::vec4& color = colors[i]; - compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - } *(vertex++) = point.x; *(vertex++) = point.y; *(vertex++) = point.z; - *(vertex++) = NORMAL.x; - *(vertex++) = NORMAL.y; - *(vertex++) = NORMAL.z; + if (i < colorCount) { + const glm::vec4& color = colors[i]; + compactColor = GeometryCache::toCompactColor(color); + } *(colorDataAt++) = compactColor; } details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData); + const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData); delete[] vertexData; delete[] colorData; @@ -1120,69 +966,55 @@ void GeometryCache::updateVertices(int id, const QVector& points, con #endif // def WANT_DEBUG } - const int FLOATS_PER_VERTEX = 3 + 3 + 2; // vertices + normals + tex coords + const int FLOATS_PER_VERTEX = 3 + 2; // vertices + tex coords const int NUM_POS_COORDS = 3; - const int NUM_NORMAL_COORDS = 3; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); - const int VERTEX_TEX_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float); + const int VERTEX_TEX_OFFSET = NUM_POS_COORDS * sizeof(float); details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); auto stream = std::make_shared(); details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEX_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, 1, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, 2, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(2)._stride); assert(points.size() == texCoords.size()); - details.vertices = points.size(); - details.vertexSize = FLOATS_PER_VERTEX; - - int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX]; float* vertex = vertexData; - int* colorData = new int[details.vertices]; - int* colorDataAt = colorData; - - const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); for (int i = 0; i < points.size(); i++) { glm::vec3 point = points[i]; glm::vec2 texCoord = texCoords[i]; *(vertex++) = point.x; *(vertex++) = point.y; *(vertex++) = point.z; - *(vertex++) = NORMAL.x; - *(vertex++) = NORMAL.y; - *(vertex++) = NORMAL.z; *(vertex++) = texCoord.x; *(vertex++) = texCoord.y; - - *(colorDataAt++) = compactColor; } - details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData); - details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData); + details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*)vertexData); + const glm::vec3 NORMAL(0.0f, -1.0f, 0.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); + int compactColor = GeometryCache::toCompactColor(color); + details.colorBuffer->append(sizeof(compactColor), (gpu::Byte*) &compactColor); delete[] vertexData; - delete[] colorData; #ifdef WANT_DEBUG qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size(); @@ -1239,12 +1071,11 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); - - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::POSITION)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::COLOR)._stride); float vertexBuffer[NUM_FLOATS]; // only vertices, no normals because we're a 2D quad int vertexPoint = 0; @@ -1283,16 +1114,9 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int vertexBuffer[vertexPoint++] = x + width; vertexBuffer[vertexPoint++] = y + bevelDistance; - int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - int colors[NUM_VERTICES] = { compactColor, compactColor, compactColor, compactColor, - compactColor, compactColor, compactColor, compactColor }; - - details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); - details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); + int compactColor = GeometryCache::toCompactColor(color); + details.colorBuffer->append(sizeof(compactColor), (gpu::Byte*) &compactColor); } batch.setInputFormat(details.streamFormat); @@ -1322,52 +1146,46 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co #endif // def WANT_DEBUG } - const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals - const int VERTICES = 4; // 1 quad = 4 vertices - const int NUM_POS_COORDS = 2; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); - if (!details.isCreated) { + static const int FLOATS_PER_VERTEX = 2; // vertices + static const int VERTICES = 4; // 1 quad = 4 vertices details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); auto stream = std::make_shared(); details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::POSITION)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::NORMAL)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::COLOR)._stride); - - const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { - minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, - maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, - minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, - maxCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, + minCorner.x, minCorner.y, + maxCorner.x, minCorner.y, + minCorner.x, maxCorner.y, + maxCorner.x, maxCorner.y, }; - const int NUM_COLOR_SCALARS_PER_QUAD = 4; - int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; - details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); - details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); + const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); + int compactColor = GeometryCache::toCompactColor(color); + details.colorBuffer->append(sizeof(compactColor), (gpu::Byte*) &compactColor); } batch.setInputFormat(details.streamFormat); @@ -1409,59 +1227,49 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co #endif // def WANT_DEBUG } - const int FLOATS_PER_VERTEX = 2 + 3 + 2; // vertices + normals + tex coords - const int VERTICES = 4; // 1 quad = 4 vertices - const int NUM_POS_COORDS = 2; - const int NUM_NORMAL_COORDS = 3; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); - const int VERTEX_TEXCOORD_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float); - if (!details.isCreated) { + static const int FLOATS_PER_VERTEX = 2 + 2; // vertices + tex coords + static const int VERTICES = 4; // 1 quad = 4 vertices + static const int NUM_POS_COORDS = 2; + static const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); - auto streamFormat = std::make_shared(); auto stream = std::make_shared(); details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; details.colorBuffer = colorBuffer; - details.streamFormat = streamFormat; details.stream = stream; - // zzmp: fix the normal across all renderQuad - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ)); details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, 1, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, 2, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(2)._stride); - - const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { - minCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMinCorner.y, - maxCorner.x, minCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMaxCorner.x, texCoordMinCorner.y, - minCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMinCorner.x, texCoordMaxCorner.y, - maxCorner.x, maxCorner.y, NORMAL.x, NORMAL.y, NORMAL.z, texCoordMaxCorner.x, texCoordMaxCorner.y, + minCorner.x, minCorner.y, texCoordMinCorner.x, texCoordMinCorner.y, + maxCorner.x, minCorner.y, texCoordMaxCorner.x, texCoordMinCorner.y, + minCorner.x, maxCorner.y, texCoordMinCorner.x, texCoordMaxCorner.y, + maxCorner.x, maxCorner.y, texCoordMaxCorner.x, texCoordMaxCorner.y, }; - - const int NUM_COLOR_SCALARS_PER_QUAD = 4; - int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; - details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); - details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); + const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); + int compactColor = GeometryCache::toCompactColor(color); + details.colorBuffer->append(sizeof(compactColor), (gpu::Byte*) &compactColor); } batch.setInputFormat(details.streamFormat); @@ -1491,54 +1299,46 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co #endif // def WANT_DEBUG } - const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals - const int VERTICES = 4; // 1 quad = 4 vertices - const int NUM_POS_COORDS = 3; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); - if (!details.isCreated) { + static const int FLOATS_PER_VERTEX = 3; // vertices + static const int VERTICES = 4; // 1 quad = 4 vertices details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); - auto streamFormat = std::make_shared(); auto stream = std::make_shared(); details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; details.colorBuffer = colorBuffer; - details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::POSITION)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::NORMAL)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::COLOR)._stride); - - const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { - minCorner.x, minCorner.y, minCorner.z, NORMAL.x, NORMAL.y, NORMAL.z, - maxCorner.x, minCorner.y, minCorner.z, NORMAL.x, NORMAL.y, NORMAL.z, - minCorner.x, maxCorner.y, maxCorner.z, NORMAL.x, NORMAL.y, NORMAL.z, - maxCorner.x, maxCorner.y, maxCorner.z, NORMAL.x, NORMAL.y, NORMAL.z, + minCorner.x, minCorner.y, minCorner.z, + maxCorner.x, minCorner.y, minCorner.z, + minCorner.x, maxCorner.y, maxCorner.z, + maxCorner.x, maxCorner.y, maxCorner.z, }; - const int NUM_COLOR_SCALARS_PER_QUAD = 4; - int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; - details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); - details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); + const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); + int compactColor = GeometryCache::toCompactColor(color); + details.colorBuffer->append(sizeof(compactColor), (gpu::Byte*) &compactColor); } batch.setInputFormat(details.streamFormat); @@ -1587,56 +1387,49 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons #endif // def WANT_DEBUG } - const int FLOATS_PER_VERTEX = 3 + 3 + 2; // vertices + normals + tex coords - const int VERTICES = 4; // 1 quad = 4 vertices - const int NUM_POS_COORDS = 3; - const int NUM_NORMAL_COORDS = 3; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); - const int VERTEX_TEXCOORD_OFFSET = VERTEX_NORMAL_OFFSET + NUM_NORMAL_COORDS * sizeof(float); - - if (!details.isCreated) { + static const int FLOATS_PER_VERTEX = 3 + 2; // vertices + tex coords + static const int VERTICES = 4; // 1 quad = 4 vertices + static const int NUM_POS_COORDS = 3; + static const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); details.isCreated = true; details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; // NOTE: this isn't used for BatchItemDetails maybe we can get rid of it auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); auto stream = std::make_shared(); - details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; + details.colorBuffer = colorBuffer; details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, 1, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, 2, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(1)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(2)._stride); - - const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { - bottomLeft.x, bottomLeft.y, bottomLeft.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordBottomLeft.x, texCoordBottomLeft.y, - bottomRight.x, bottomRight.y, bottomRight.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordBottomRight.x, texCoordBottomRight.y, - topLeft.x, topLeft.y, topLeft.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordTopLeft.x, texCoordTopLeft.y, - topRight.x, topRight.y, topRight.z, NORMAL.x, NORMAL.y, NORMAL.z, texCoordTopRight.x, texCoordTopRight.y, + bottomLeft.x, bottomLeft.y, bottomLeft.z, texCoordBottomLeft.x, texCoordBottomLeft.y, + bottomRight.x, bottomRight.y, bottomRight.z, texCoordBottomRight.x, texCoordBottomRight.y, + topLeft.x, topLeft.y, topLeft.z, texCoordTopLeft.x, texCoordTopLeft.y, + topRight.x, topRight.y, topRight.z, texCoordTopRight.x, texCoordTopRight.y, }; - const int NUM_COLOR_SCALARS_PER_QUAD = 4; - int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - int colors[NUM_COLOR_SCALARS_PER_QUAD] = { compactColor, compactColor, compactColor, compactColor }; - details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); - details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); + const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); + int compactColor = GeometryCache::toCompactColor(color); + details.colorBuffer->append(sizeof(compactColor), (gpu::Byte*) &compactColor); } batch.setInputFormat(details.streamFormat); @@ -1644,6 +1437,88 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } +void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, + const glm::vec4& color1, const glm::vec4& color2, int id) { + + bool registered = (id != UNKNOWN_ID); + Vec3Pair key(p1, p2); + + BatchItemDetails& details = _registeredLine3DVBOs[id]; + + // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed + if (registered && details.isCreated) { + Vec3Pair& lastKey = _lastRegisteredLine3D[id]; + if (lastKey != key) { + details.clear(); + _lastRegisteredLine3D[id] = key; +#ifdef WANT_DEBUG + qCDebug(renderutils) << "renderLine() 3D ... RELEASING REGISTERED line"; +#endif // def WANT_DEBUG + } +#ifdef WANT_DEBUG + else { + qCDebug(renderutils) << "renderLine() 3D ... REUSING PREVIOUSLY REGISTERED line"; + } +#endif // def WANT_DEBUG + } + + if (!details.isCreated) { + static const int FLOATS_PER_VERTEX = 3; // vertices + static const int vertices = 2; + + details.isCreated = true; + details.vertices = vertices; + details.vertexSize = FLOATS_PER_VERTEX; + + auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); + auto colorBuffer = std::make_shared(); + auto streamFormat = std::make_shared(); + auto stream = std::make_shared(); + + details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; + details.colorBuffer = colorBuffer; + details.streamFormat = streamFormat; + details.stream = stream; + + details.streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::POSITION)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::NORMAL)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::COLOR)._stride); + + float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { + p1.x, p1.y, p1.z, + p2.x, p2.y, p2.z + }; + + const int NUM_COLOR_SCALARS = 2; + int compactColor1 = GeometryCache::toCompactColor(color1); + int compactColor2 = GeometryCache::toCompactColor(color2); + int colors[NUM_COLOR_SCALARS] = { compactColor1, compactColor2 }; + + details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); + const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); + details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); + +#ifdef WANT_DEBUG + if (id == UNKNOWN_ID) { + qCDebug(renderutils) << "new renderLine() 3D VBO made -- _line3DVBOs.size():" << _line3DVBOs.size(); + } else { + qCDebug(renderutils) << "new registered renderLine() 3D VBO made -- _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); + } +#endif + } + + batch.setInputFormat(details.streamFormat); + batch.setInputStream(0, *details.stream); + batch.draw(gpu::LINES, 2, 0); +} + void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, const float dash_length, const float gap_length, int id) { @@ -1664,11 +1539,6 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, if (!details.isCreated) { - int compactColor = ((int(color.x * 255.0f) & 0xFF)) | - ((int(color.y * 255.0f) & 0xFF) << 8) | - ((int(color.z * 255.0f) & 0xFF) << 16) | - ((int(color.w * 255.0f) & 0xFF) << 24); - // draw each line segment with appropriate gaps const float SEGMENT_LENGTH = dash_length + gap_length; float length = glm::distance(start, end); @@ -1679,77 +1549,60 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, glm::vec3 dashVector = segmentVector / SEGMENT_LENGTH * dash_length; glm::vec3 gapVector = segmentVector / SEGMENT_LENGTH * gap_length; - const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals - const int NUM_POS_COORDS = 3; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); + const int FLOATS_PER_VERTEX = 3; // vertices + details.isCreated = true; details.vertices = (segmentCountFloor + 1) * 2; details.vertexSize = FLOATS_PER_VERTEX; - details.isCreated = true; auto verticesBuffer = std::make_shared(); + auto normalBuffer = std::make_shared(); auto colorBuffer = std::make_shared(); auto streamFormat = std::make_shared(); auto stream = std::make_shared(); details.verticesBuffer = verticesBuffer; + details.normalBuffer = normalBuffer; details.colorBuffer = colorBuffer; details.streamFormat = streamFormat; details.stream = stream; - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + details.streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + details.streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), 0, gpu::Stream::PER_INSTANCE); - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - - int* colorData = new int[details.vertices]; - int* colorDataAt = colorData; + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::POSITION)._stride); + details.stream->addBuffer(details.normalBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::NORMAL)._stride); + details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(gpu::Stream::COLOR)._stride); float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX]; float* vertex = vertexData; - const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f); glm::vec3 point = start; *(vertex++) = point.x; *(vertex++) = point.y; *(vertex++) = point.z; - *(vertex++) = NORMAL.x; - *(vertex++) = NORMAL.y; - *(vertex++) = NORMAL.z; - *(colorDataAt++) = compactColor; for (int i = 0; i < segmentCountFloor; i++) { point += dashVector; *(vertex++) = point.x; *(vertex++) = point.y; *(vertex++) = point.z; - *(vertex++) = NORMAL.x; - *(vertex++) = NORMAL.y; - *(vertex++) = NORMAL.z; - *(colorDataAt++) = compactColor; point += gapVector; *(vertex++) = point.x; *(vertex++) = point.y; *(vertex++) = point.z; - *(vertex++) = NORMAL.x; - *(vertex++) = NORMAL.y; - *(vertex++) = NORMAL.z; - *(colorDataAt++) = compactColor; } *(vertex++) = end.x; *(vertex++) = end.y; *(vertex++) = end.z; - *(vertex++) = NORMAL.x; - *(vertex++) = NORMAL.y; - *(vertex++) = NORMAL.z; - *(colorDataAt++) = compactColor; details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData); - details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData); + const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f); + details.normalBuffer->append(3 * sizeof(float), (gpu::Byte*) glm::value_ptr(NORMAL)); + int compactColor = GeometryCache::toCompactColor(color); + details.colorBuffer->append(sizeof(compactColor), (gpu::Byte*) &compactColor); delete[] vertexData; - delete[] colorData; #ifdef WANT_DEBUG if (registered) { @@ -1770,6 +1623,7 @@ int GeometryCache::BatchItemDetails::population = 0; GeometryCache::BatchItemDetails::BatchItemDetails() : verticesBuffer(NULL), +normalBuffer(NULL), colorBuffer(NULL), streamFormat(NULL), stream(NULL), @@ -1784,6 +1638,7 @@ isCreated(false) { GeometryCache::BatchItemDetails::BatchItemDetails(const GeometryCache::BatchItemDetails& other) : verticesBuffer(other.verticesBuffer), +normalBuffer(other.normalBuffer), colorBuffer(other.colorBuffer), streamFormat(other.streamFormat), stream(other.stream), @@ -1808,184 +1663,12 @@ void GeometryCache::BatchItemDetails::clear() { isCreated = false; uniformBuffer.reset(); verticesBuffer.reset(); + normalBuffer.reset(); colorBuffer.reset(); streamFormat.reset(); stream.reset(); } -void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, - const glm::vec4& color1, const glm::vec4& color2, int id) { - - bool registered = (id != UNKNOWN_ID); - Vec3Pair key(p1, p2); - - BatchItemDetails& details = _registeredLine3DVBOs[id]; - - int compactColor1 = ((int(color1.x * 255.0f) & 0xFF)) | - ((int(color1.y * 255.0f) & 0xFF) << 8) | - ((int(color1.z * 255.0f) & 0xFF) << 16) | - ((int(color1.w * 255.0f) & 0xFF) << 24); - - int compactColor2 = ((int(color2.x * 255.0f) & 0xFF)) | - ((int(color2.y * 255.0f) & 0xFF) << 8) | - ((int(color2.z * 255.0f) & 0xFF) << 16) | - ((int(color2.w * 255.0f) & 0xFF) << 24); - - - // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed - if (registered && details.isCreated) { - Vec3Pair& lastKey = _lastRegisteredLine3D[id]; - if (lastKey != key) { - details.clear(); - _lastRegisteredLine3D[id] = key; -#ifdef WANT_DEBUG - qCDebug(renderutils) << "renderLine() 3D ... RELEASING REGISTERED line"; -#endif // def WANT_DEBUG - } -#ifdef WANT_DEBUG - else { - qCDebug(renderutils) << "renderLine() 3D ... REUSING PREVIOUSLY REGISTERED line"; - } -#endif // def WANT_DEBUG - } - - const int FLOATS_PER_VERTEX = 3 + 3; // vertices + normals - const int NUM_POS_COORDS = 3; - const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); - const int vertices = 2; - if (!details.isCreated) { - - details.isCreated = true; - details.vertices = vertices; - details.vertexSize = FLOATS_PER_VERTEX; - - auto verticesBuffer = std::make_shared(); - auto colorBuffer = std::make_shared(); - auto streamFormat = std::make_shared(); - auto stream = std::make_shared(); - - details.verticesBuffer = verticesBuffer; - details.colorBuffer = colorBuffer; - details.streamFormat = streamFormat; - details.stream = stream; - - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); - - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - - const glm::vec3 NORMAL(1.0f, 0.0f, 0.0f); - float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { - p1.x, p1.y, p1.z, NORMAL.x, NORMAL.y, NORMAL.z, - p2.x, p2.y, p2.z, NORMAL.x, NORMAL.y, NORMAL.z }; - - const int NUM_COLOR_SCALARS = 2; - int colors[NUM_COLOR_SCALARS] = { compactColor1, compactColor2 }; - - details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); - details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); - -#ifdef WANT_DEBUG - if (id == UNKNOWN_ID) { - qCDebug(renderutils) << "new renderLine() 3D VBO made -- _line3DVBOs.size():" << _line3DVBOs.size(); - } else { - qCDebug(renderutils) << "new registered renderLine() 3D VBO made -- _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); - } -#endif - } - - // this is what it takes to render a quad - batch.setInputFormat(details.streamFormat); - batch.setInputStream(0, *details.stream); - batch.draw(gpu::LINES, 2, 0); -} - -void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, - const glm::vec4& color1, const glm::vec4& color2, int id) { - - bool registered = (id != UNKNOWN_ID); - Vec2Pair key(p1, p2); - - BatchItemDetails& details = _registeredLine2DVBOs[id]; - - int compactColor1 = ((int(color1.x * 255.0f) & 0xFF)) | - ((int(color1.y * 255.0f) & 0xFF) << 8) | - ((int(color1.z * 255.0f) & 0xFF) << 16) | - ((int(color1.w * 255.0f) & 0xFF) << 24); - - int compactColor2 = ((int(color2.x * 255.0f) & 0xFF)) | - ((int(color2.y * 255.0f) & 0xFF) << 8) | - ((int(color2.z * 255.0f) & 0xFF) << 16) | - ((int(color2.w * 255.0f) & 0xFF) << 24); - - - // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed - if (registered && details.isCreated) { - Vec2Pair& lastKey = _lastRegisteredLine2D[id]; - if (lastKey != key) { - details.clear(); - _lastRegisteredLine2D[id] = key; -#ifdef WANT_DEBUG - qCDebug(renderutils) << "renderLine() 2D ... RELEASING REGISTERED line"; -#endif // def WANT_DEBUG - } -#ifdef WANT_DEBUG - else { - qCDebug(renderutils) << "renderLine() 2D ... REUSING PREVIOUSLY REGISTERED line"; - } -#endif // def WANT_DEBUG - } - - const int FLOATS_PER_VERTEX = 2; - const int vertices = 2; - if (!details.isCreated) { - - details.isCreated = true; - details.vertices = vertices; - details.vertexSize = FLOATS_PER_VERTEX; - - auto verticesBuffer = std::make_shared(); - auto colorBuffer = std::make_shared(); - auto streamFormat = std::make_shared(); - auto stream = std::make_shared(); - - details.verticesBuffer = verticesBuffer; - details.colorBuffer = colorBuffer; - details.streamFormat = streamFormat; - details.stream = stream; - - details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); - - details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); - details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - - - float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { p1.x, p1.y, p2.x, p2.y }; - - const int NUM_COLOR_SCALARS = 2; - int colors[NUM_COLOR_SCALARS] = { compactColor1, compactColor2 }; - - details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); - details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); - -#ifdef WANT_DEBUG - if (id == UNKNOWN_ID) { - qCDebug(renderutils) << "new renderLine() 2D VBO made -- _line3DVBOs.size():" << _line2DVBOs.size(); - } else { - qCDebug(renderutils) << "new registered renderLine() 2D VBO made -- _registeredLine2DVBOs.size():" << _registeredLine2DVBOs.size(); - } -#endif - } - - // this is what it takes to render a quad - batch.setInputFormat(details.streamFormat); - batch.setInputStream(0, *details.stream); - batch.draw(gpu::LINES, 2, 0); -} - void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) { static std::once_flag once; std::call_once(once, [&]() { @@ -2175,24 +1858,24 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp std::call_once(once, [&]() { using namespace shader::render_utils::program; - _forwardSimpleShader = gpu::Shader::createProgram(simple_forward); - _forwardTransparentShader = gpu::Shader::createProgram(simple_translucent_forward); - _forwardUnlitShader = gpu::Shader::createProgram(simple_unlit_forward); + _shapeShaders[std::make_tuple(false, false, true, false)] = gpu::Shader::createProgram(simple_forward); + _shapeShaders[std::make_tuple(true, false, true, false)] = gpu::Shader::createProgram(simple_translucent_forward); + _shapeShaders[std::make_tuple(false, true, true, false)] = gpu::Shader::createProgram(simple_unlit_forward); - _simpleShader = gpu::Shader::createProgram(simple); - _transparentShader = gpu::Shader::createProgram(simple_translucent); - _unlitShader = gpu::Shader::createProgram(simple_unlit); + _shapeShaders[std::make_tuple(false, false, false, false)] = gpu::Shader::createProgram(simple); + _shapeShaders[std::make_tuple(true, false, false, false)] = gpu::Shader::createProgram(simple_translucent); + _shapeShaders[std::make_tuple(false, true, false, false)] = gpu::Shader::createProgram(simple_unlit); }); } else { static std::once_flag once; std::call_once(once, [&]() { using namespace shader::render_utils::program; // Fading is currently disabled during forward rendering - _forwardSimpleFadeShader = gpu::Shader::createProgram(simple_forward); - _forwardUnlitFadeShader = gpu::Shader::createProgram(simple_unlit_forward); + _shapeShaders[std::make_tuple(false, false, true, true)] = gpu::Shader::createProgram(simple_forward); + _shapeShaders[std::make_tuple(false, true, true, true)] = gpu::Shader::createProgram(simple_unlit_forward); - _simpleFadeShader = gpu::Shader::createProgram(simple_fade); - _unlitFadeShader = gpu::Shader::createProgram(simple_unlit_fade); + _shapeShaders[std::make_tuple(false, false, false, true)] = gpu::Shader::createProgram(simple_fade); + _shapeShaders[std::make_tuple(false, true, false, true)] = gpu::Shader::createProgram(simple_unlit_fade); }); } @@ -2220,20 +1903,13 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp PrepareStencil::testMaskDrawShapeNoAA(*state); } - gpu::ShaderPointer program; - if (config.isForward()) { - program = (config.isUnlit()) ? (config.isFading() ? _forwardUnlitFadeShader : _forwardUnlitShader) : - (config.isFading() ? _forwardSimpleFadeShader : (config.isTransparent() ? _forwardTransparentShader : _forwardSimpleShader)); - } else { - program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : - (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader)); - } + gpu::ShaderPointer program = _shapeShaders[std::make_tuple(config.isTransparent(), config.isUnlit(), config.isForward(), config.isFading())]; gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); _simplePrograms.insert(config, pipeline); return pipeline; } -uint32_t toCompactColor(const glm::vec4& color) { +uint32_t GeometryCache::toCompactColor(const glm::vec4& color) { uint32_t compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | ((int(color.z * 255.0f) & 0xFF) << 16) | @@ -2251,7 +1927,7 @@ void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color // Add color to named buffer { gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(instanceName, INSTANCE_COLOR_BUFFER); - auto compactColor = toCompactColor(color); + const uint32_t compactColor = GeometryCache::toCompactColor(color); instanceColorBuffer->append(compactColor); } @@ -2268,55 +1944,6 @@ void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color }); } -static const size_t INSTANCE_FADE_BUFFER1 = 1; -static const size_t INSTANCE_FADE_BUFFER2 = 2; -static const size_t INSTANCE_FADE_BUFFER3 = 3; - -void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, int fadeCategory, float fadeThreshold, - const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, bool isWire, - const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) { - // Add pipeline to name - std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash()(pipeline)); - - // Add color to named buffer - { - gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(instanceName, INSTANCE_COLOR_BUFFER); - auto compactColor = toCompactColor(color); - instanceColorBuffer->append(compactColor); - } - // Add fade parameters to named buffers - { - gpu::BufferPointer fadeBuffer1 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER1); - gpu::BufferPointer fadeBuffer2 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER2); - gpu::BufferPointer fadeBuffer3 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER3); - // Pack parameters in 3 vec4s - glm::vec4 fadeData1; - glm::vec4 fadeData2; - glm::vec4 fadeData3; - FadeEffect::packToAttributes(fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, - fadeData1, fadeData2, fadeData3); - fadeBuffer1->append(fadeData1); - fadeBuffer2->append(fadeData2); - fadeBuffer3->append(fadeData3); - } - - // Add call to named buffer - batch.setupNamedCalls(instanceName, [args, isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - auto& buffers = data.buffers; - batch.setPipeline(pipeline->pipeline); - pipeline->prepare(batch, args); - - if (isWire) { - DependencyManager::get()->renderWireFadeShapeInstances(batch, shape, data.count(), - buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); - } - else { - DependencyManager::get()->renderFadeShapeInstances(batch, shape, data.count(), - buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); - } - }); -} - void GeometryCache::renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderInstances(args, batch, color, false, pipeline, shape); @@ -2327,74 +1954,11 @@ void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, renderInstances(args, batch, color, true, pipeline, shape); } -void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, - int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, - const render::ShapePipelinePointer& pipeline) { - assert(pipeline != nullptr); - renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, false, pipeline, shape); -} - -void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, - int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, - const render::ShapePipelinePointer& pipeline) { - assert(pipeline != nullptr); - renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, true, pipeline, shape); -} - void GeometryCache::renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderInstances(args, batch, color, false, pipeline, GeometryCache::Sphere); } -void GeometryCache::renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { - assert(pipeline != nullptr); - renderInstances(args, batch, color, true, pipeline, GeometryCache::Sphere); -} - -// Enable this in a debug build to cause 'box' entities to iterate through all the -// available shape types, both solid and wireframes -//#define DEBUG_SHAPES - - -void GeometryCache::renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { - assert(pipeline != nullptr); -#ifdef DEBUG_SHAPES - static auto startTime = usecTimestampNow(); - renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { - - auto usecs = usecTimestampNow(); - usecs -= startTime; - auto msecs = usecs / USECS_PER_MSEC; - float seconds = msecs; - seconds /= MSECS_PER_SECOND; - float fractionalSeconds = seconds - floor(seconds); - int shapeIndex = (int)seconds; - - // Every second we flip to the next shape. - static const int SHAPE_COUNT = 5; - GeometryCache::Shape shapes[SHAPE_COUNT] = { - GeometryCache::Cube, - GeometryCache::Tetrahedron, - GeometryCache::Sphere, - GeometryCache::Icosahedron, - GeometryCache::Line, - }; - - shapeIndex %= SHAPE_COUNT; - GeometryCache::Shape shape = shapes[shapeIndex]; - - // For the first half second for a given shape, show the wireframe, for the second half, show the solid. - if (fractionalSeconds > 0.5f) { - renderInstances(INSTANCE_NAME, batch, color, true, pipeline, shape); - } else { - renderInstances(INSTANCE_NAME, batch, color, false, pipeline, shape); - } - }); -#else - renderInstances(args, batch, color, false, pipeline, GeometryCache::Cube); -#endif -} - void GeometryCache::renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { static const std::string INSTANCE_NAME = __FUNCTION__; assert(pipeline != nullptr); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 179d49c076..3f06a6b1a3 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -180,31 +180,10 @@ public: void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); - void renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, - gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3); - void renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, - gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3); - void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, - const render::ShapePipelinePointer& pipeline); - void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline) { - renderSolidShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline); - } - + const render::ShapePipelinePointer& pipeline); void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline); - void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline) { - renderWireShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline); - } - - void renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, int fadeCategory, float fadeThreshold, - const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, - const render::ShapePipelinePointer& pipeline); - void renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color, int fadeCategory, float fadeThreshold, - const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, - const render::ShapePipelinePointer& pipeline); void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline); @@ -213,20 +192,6 @@ public: renderSolidSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, - const render::ShapePipelinePointer& pipeline); - void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline) { - renderWireSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline); - } - - void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, - const render::ShapePipelinePointer& pipeline); - void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline) { - renderSolidCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline); - } - void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline); void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, @@ -235,24 +200,10 @@ public: } // Dynamic geometry - void renderShape(gpu::Batch& batch, Shape shape); - void renderWireShape(gpu::Batch& batch, Shape shape); - void renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); - void renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); + void renderShape(gpu::Batch& batch, Shape shape, gpu::BufferPointer& colorBuffer); + void renderWireShape(gpu::Batch& batch, Shape shape, gpu::BufferPointer& colorBuffer); size_t getShapeTriangleCount(Shape shape); - void renderCube(gpu::Batch& batch); - void renderWireCube(gpu::Batch& batch); - void renderCube(gpu::Batch& batch, const glm::vec4& color); - void renderWireCube(gpu::Batch& batch, const glm::vec4& color); - size_t getCubeTriangleCount(); - - void renderSphere(gpu::Batch& batch); - void renderWireSphere(gpu::Batch& batch); - void renderSphere(gpu::Batch& batch, const glm::vec4& color); - void renderWireSphere(gpu::Batch& batch, const glm::vec4& color); - size_t getSphereTriangleCount(); - void renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, int majorRows, int majorCols, float majorEdge, int minorRows, int minorCols, float minorEdge, @@ -262,10 +213,6 @@ public: void renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id); - void renderUnitQuad(gpu::Batch& batch, int id) { - renderUnitQuad(batch, glm::vec4(1), id); - } - void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id) { renderQuad(batch, glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); } @@ -307,19 +254,6 @@ public: void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, const float dash_length, const float gap_length, int id); - void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id) - { renderLine(batch, p1, p2, glm::vec4(color, 1.0f), id); } - - void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id) - { renderLine(batch, p1, p2, color, color, id); } - - void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, - const glm::vec3& color1, const glm::vec3& color2, int id) - { renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); } - - void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, - const glm::vec4& color1, const glm::vec4& color2, int id); - void updateVertices(int id, const QVector& points, const glm::vec4& color); void updateVertices(int id, const QVector& points, const QVector& colors); void updateVertices(int id, const QVector& points, const glm::vec4& color); @@ -364,6 +298,8 @@ public: graphics::MeshPointer meshFromShape(Shape geometryShape, glm::vec3 color); + static uint32_t toCompactColor(const glm::vec4& color); + private: GeometryCache(); @@ -397,6 +333,7 @@ private: public: static int population; gpu::BufferPointer verticesBuffer; + gpu::BufferPointer normalBuffer; gpu::BufferPointer colorBuffer; gpu::BufferPointer uniformBuffer; gpu::Stream::FormatPointer streamFormat; @@ -445,18 +382,9 @@ private: QHash _lastRegisteredGridBuffer; QHash _registeredGridBuffers; - // FIXME: clean these up - static gpu::ShaderPointer _simpleShader; - static gpu::ShaderPointer _transparentShader; - static gpu::ShaderPointer _unlitShader; - static gpu::ShaderPointer _simpleFadeShader; - static gpu::ShaderPointer _unlitFadeShader; - static gpu::ShaderPointer _forwardSimpleShader; - static gpu::ShaderPointer _forwardTransparentShader; - static gpu::ShaderPointer _forwardUnlitShader; - static gpu::ShaderPointer _forwardSimpleFadeShader; - static gpu::ShaderPointer _forwardUnlitFadeShader; - + // transparent, unlit, forward, fade + static std::map, gpu::ShaderPointer> _shapeShaders; + // transparent, unlit, forward static std::map, render::ShapePipelinePointer> _shapePipelines; static QHash _simplePrograms; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index f6e4b3b460..e095d9b15d 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -354,12 +354,17 @@ void ModelMeshPartPayload::render(RenderArgs* args) { outColor = procedural->getColor(outColor); procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned())); - batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); + + const uint32_t compactColor = GeometryCache::toCompactColor(glm::vec4(outColor)); + _drawMesh->getColorBuffer()->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); } else { // apply material properties if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { args->_details._materialSwitches++; } + + const uint32_t compactColor = 0xFFFFFFFF; + _drawMesh->getColorBuffer()->setData(sizeof(compactColor), (const gpu::Byte*) &compactColor); } // Draw! diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 474a8f467d..74734fdc43 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -279,6 +279,7 @@ bool QmlWindowClass::isVisible() { return quickItem->isVisible(); } else { qDebug() << "QmlWindowClass::isVisible: asQuickItem() returned NULL"; + return false; } } diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index 3a546caf69..449d1d8222 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -123,6 +123,17 @@ var copiedRotation; var copiedDimensions; + var importUiPersistedData = { + "elJsonUrl": "", + "elImportAtAvatar": true, + "elImportAtSpecificPosition": false, + "elPositionX": 0, + "elPositionY": 0, + "elPositionZ": 0, + "elEntityHostTypeDomain": true, + "elEntityHostTypeAvatar": false + }; + var cameraManager = new CameraManager(); var grid = new Grid(); @@ -2010,7 +2021,8 @@ return position; } - function importSVO(importURL) { + function importSVO(importURL, importEntityHostType) { + importEntityHostType = importEntityHostType || "domain"; if (!Entities.canRez() && !Entities.canRezTmp()) { Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); return; @@ -2033,7 +2045,7 @@ position = createApp.getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2); } if (position !== null && position !== undefined) { - var pastedEntityIDs = Clipboard.pasteEntities(position); + var pastedEntityIDs = Clipboard.pasteEntities(position, importEntityHostType); if (!isLargeImport) { // The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move // entities after they're imported so that they're all the correct distance in front of and with geometric mean @@ -2813,6 +2825,72 @@ type: 'zoneListRequest', zones: getExistingZoneList() }); + } else if (data.type === "importUiBrowse") { + let fileToImport = Window.browse("Select .json to Import", "", "*.json"); + if (fileToImport !== null) { + emitScriptEvent({ + type: 'importUi_SELECTED_FILE', + file: fileToImport + }); + } else { + audioFeedback.rejection(); + } + } else if (data.type === "importUiImport") { + if ((data.entityHostType === "domain" && Entities.canAdjustLocks() && Entities.canRez()) || + (data.entityHostType === "avatar" && Entities.canRezAvatarEntities())) { + if (data.positioningMode === "avatar") { + importSVO(data.jsonURL, data.entityHostType); + } else { + if (Clipboard.importEntities(data.jsonURL)) { + let importedPastedEntities = Clipboard.pasteEntities(data.position, data.entityHostType); + if (importedPastedEntities.length === 0) { + emitScriptEvent({ + type: 'importUi_IMPORT_ERROR', + reason: "No Entity has been imported." + }); + } else { + if (isActive) { + selectionManager.setSelections(importedPastedEntities, this); + } + emitScriptEvent({type: 'importUi_IMPORT_CONFIRMATION'}); + } + } else { + emitScriptEvent({ + type: 'importUi_IMPORT_ERROR', + reason: "Import Entities has failed." + }); + } + } + } else { + emitScriptEvent({ + type: 'importUi_IMPORT_ERROR', + reason: "You don't have permission to create in this domain." + }); + } + } else if (data.type === "importUiGoBack") { + if (location.canGoBack()) { + location.goBack(); + } else { + audioFeedback.rejection(); + } + } else if (data.type === "importUiGoTutorial") { + Window.location = "file:///~/serverless/tutorial.json"; + } else if (data.type === "importUiGetCopiedPosition") { + if (copiedPosition !== undefined) { + emitScriptEvent({ + type: 'importUi_POSITION_TO_PASTE', + position: copiedPosition + }); + } else { + audioFeedback.rejection(); + } + } else if (data.type === "importUiPersistData") { + importUiPersistedData = data.importUiPersistedData; + } else if (data.type === "importUiGetPersistData") { + emitScriptEvent({ + type: 'importUi_LOAD_DATA', + importUiPersistedData: importUiPersistedData + }); } }; diff --git a/scripts/system/create/importEntities/html/css/importEntities.css b/scripts/system/create/importEntities/html/css/importEntities.css new file mode 100644 index 0000000000..61c75dabb3 --- /dev/null +++ b/scripts/system/create/importEntities/html/css/importEntities.css @@ -0,0 +1,160 @@ +/* +// importEntities.css +// +// Created by Alezia Kurdis on March 13th, 2024 +// Copyright 2024 Overte e.V. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +@font-face { + font-family: FiraSans-SemiBold; + src: url(../../../../../../resources/fonts/FiraSans-SemiBold.ttf), /* Windows production */ + url(../../../../../../fonts/FiraSans-SemiBold.ttf); /* OSX production */ +} + +@font-face { + font-family: FiraSans-Regular; + src: url(../../../../../../resources/fonts/FiraSans-Regular.ttf), /* Windows production */ + url(../../../../../../fonts/FiraSans-Regular.ttf); /* OSX production */ +} + +@font-face { + font-family: Raleway-Bold; + src: url(../../../../../../resources/fonts/Raleway-Bold.ttf), /* Windows production */ + url(../../../../../../fonts/Raleway-Bold.ttf); /* OSX production */ +} + +html { + width: 100%; + height: 100%; +} +input[type="text"] { + font-family: FiraSans-SemiBold; + color: #BBBBBB; + background-color: #222222; + border: 0; + padding: 4px; + margin: 1px; +} + +input[type="number"] { + font-family: FiraSans-SemiBold; + color: #BBBBBB; + background-color: #222222; + border: 0; + padding: 4px; + margin: 1px; + width: 90px; +} + +h2 { + font-size: 18px; + color: #FFFFFF; +} +body { + background: #404040; + font-family: FiraSans-Regular; + font-size: 14px; + color: #BBBBBB; + text-decoration: none; + font-style: normal; + font-variant: normal; + text-transform: none; +} + +#importAtSpecificPositionContainer { + display: none; + width: 100%; +} + +#jsonUrl { + width:90%; +} +#browseBtn { + font-family: FiraSans-SemiBold; +} +#browseBtn:hover { + +} + +label { + font-family: FiraSans-SemiBold; + color: #DDDDDD; +} +font.red { + font-family: FiraSans-SemiBold; + color: #e83333; +} +font.green { + font-family: FiraSans-SemiBold; + color: #0db518; +} +font.blue { + font-family: FiraSans-SemiBold; + color: #447ef2; +} +#importBtn { + color: #ffffff; + background-color: #1080b8; + background: linear-gradient(#00b4ef 20%, #1080b8 100%); + font-family: Raleway-Bold; + font-size: 13px; + text-transform: uppercase; + vertical-align: top; + height: 28px; + min-width: 70px; + padding: 0 18px; + margin: 3px 3px 12px 3px; + border-radius: 5px; + border: 0; + cursor: pointer; +} +#importBtn:hover { + background: linear-gradient(#00b4ef, #00b4ef); + border: none; +} +input:focus { + outline: none; + color: #FFFFFF; +} +button:focus { + outline: none; +} +div.explicative { + width: 96%; + padding: 7px; + font-family: FiraSans-SemiBold; + font-size: 12px; + text-decoration: none; + color: #BBBBBB; +} +button.black { + font-family: Raleway-Bold; + font-size: 10px; + text-transform: uppercase; + vertical-align: top; + height: 18px; + min-width: 60px; + padding: 0 14px; + margin: 5px; + border-radius: 4px; + border: none; + color: #fff; + background-color: #000; + background: linear-gradient(#343434 20%, #000 100%); + cursor: pointer; +} +button.black:hover { + background: linear-gradient(#000, #000); + border: none; +} +#messageContainer { + font-family: FiraSans-SemiBold; + width: 100%; +} +#testContainer { + border: 1px solid #AAAAAA; + padding: 0px; +} diff --git a/scripts/system/create/importEntities/html/importEntities.html b/scripts/system/create/importEntities/html/importEntities.html new file mode 100644 index 0000000000..a1550a642e --- /dev/null +++ b/scripts/system/create/importEntities/html/importEntities.html @@ -0,0 +1,77 @@ + + + + Import Entities + + + + + + +

Import Entities (.json)

+ * URL/File (.json):
+  
+
+ + + + + +
+ Position:
+    
+    
+
+
+ X     + Y     + Z
+
+
+ Note: If you import a "serverless" json file, such data include positions. + It this case, the "Position" will act as an offset. +
+
+
+
+ + + + + +
+ Entity Host Type:
+    
+    
+
+
+
+
+
+ + + + + +
+
+ For large import, it can be wise to test it in a serverless environment before doing it in your real domain. +
+
+
+ +     + +
+
+
+ + diff --git a/scripts/system/create/importEntities/html/js/importEntitiesUi.js b/scripts/system/create/importEntities/html/js/importEntitiesUi.js new file mode 100644 index 0000000000..6e80c7f173 --- /dev/null +++ b/scripts/system/create/importEntities/html/js/importEntitiesUi.js @@ -0,0 +1,217 @@ +// importEntitiesUi.js +// +// Created by Alezia Kurdis on March 13th, 2024 +// Copyright 2024 Overte e.V. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +let elJsonUrl; +let elBrowseBtn; +let elImportAtAvatar; +let elImportAtSpecificPosition; +let elImportAtSpecificPositionContainer; +let elPositionX; +let elPositionY; +let elPositionZ; +let elEntityHostTypeDomain; +let elEntityHostTypeAvatar; +let elMessageContainer; +let elImportBtn; +let elBackBtn; +let elTpTutorialBtn; +let elPastePositionBtn; + +let lockUntil; + +const LOCK_BTN_DELAY = 2000; //2 sec + +function loaded() { + lockUntil = 0; + + elJsonUrl = document.getElementById("jsonUrl"); + elBrowseBtn = document.getElementById("browseBtn"); + elImportAtAvatar = document.getElementById("importAtAvatar"); + elImportAtSpecificPosition = document.getElementById("importAtSpecificPosition"); + elImportAtSpecificPositionContainer = document.getElementById("importAtSpecificPositionContainer"); + elPositionX = document.getElementById("positionX"); + elPositionY = document.getElementById("positionY"); + elPositionZ = document.getElementById("positionZ"); + elEntityHostTypeDomain = document.getElementById("entityHostTypeDomain"); + elEntityHostTypeAvatar = document.getElementById("entityHostTypeAvatar"); + elMessageContainer = document.getElementById("messageContainer"); + elImportBtn = document.getElementById("importBtn"); + elBackBtn = document.getElementById("backBtn"); + elTpTutorialBtn = document.getElementById("tpTutorialBtn"); + elPastePositionBtn = document.getElementById("pastePositionBtn"); + + elJsonUrl.oninput = function() { + persistData(); + } + + elPositionX.oninput = function() { + persistData(); + } + + elPositionY.oninput = function() { + persistData(); + } + + elPositionZ.oninput = function() { + persistData(); + } + + elEntityHostTypeDomain.onclick = function() { + persistData(); + } + + elEntityHostTypeAvatar.onclick = function() { + persistData(); + } + + elBrowseBtn.onclick = function() { + const d = new Date(); + let time = d.getTime(); + if ((d.getTime() - lockUntil) > LOCK_BTN_DELAY) { + EventBridge.emitWebEvent(JSON.stringify({ "type": "importUiBrowse" })); + lockUntil = d.getTime() + LOCK_BTN_DELAY; + } + }; + + elImportAtAvatar.onclick = function() { + elImportAtSpecificPositionContainer.style.display = "None"; + persistData(); + }; + + elImportAtSpecificPosition.onclick = function() { + elImportAtSpecificPositionContainer.style.display = "Block"; + persistData(); + }; + + elImportBtn.onclick = function() { + const d = new Date(); + let time = d.getTime(); + if ((d.getTime() - lockUntil) > LOCK_BTN_DELAY) { + importJsonToWorld(); + lockUntil = d.getTime() + LOCK_BTN_DELAY; + } + }; + + elBackBtn.onclick = function() { + const d = new Date(); + let time = d.getTime(); + if ((d.getTime() - lockUntil) > LOCK_BTN_DELAY) { + EventBridge.emitWebEvent(JSON.stringify({ "type": "importUiGoBack" })); + lockUntil = d.getTime() + LOCK_BTN_DELAY; + } + }; + + elTpTutorialBtn.onclick = function() { + const d = new Date(); + let time = d.getTime(); + if ((d.getTime() - lockUntil) > LOCK_BTN_DELAY) { + EventBridge.emitWebEvent(JSON.stringify({ "type": "importUiGoTutorial" })); + lockUntil = d.getTime() + LOCK_BTN_DELAY; + } + }; + + elPastePositionBtn.onclick = function() { + const d = new Date(); + let time = d.getTime(); + if ((d.getTime() - lockUntil) > LOCK_BTN_DELAY) { + EventBridge.emitWebEvent(JSON.stringify({ "type": "importUiGetCopiedPosition" })); + lockUntil = d.getTime() + LOCK_BTN_DELAY; + } + }; + + EventBridge.emitWebEvent(JSON.stringify({ "type": "importUiGetPersistData" })); +} + +function persistData() { + let message = { + "type": "importUiPersistData", + "importUiPersistedData": { + "elJsonUrl": elJsonUrl.value, + "elImportAtAvatar": elImportAtAvatar.checked, + "elImportAtSpecificPosition": elImportAtSpecificPosition.checked, + "elPositionX": elPositionX.value, + "elPositionY": elPositionY.value, + "elPositionZ": elPositionZ.value, + "elEntityHostTypeDomain": elEntityHostTypeDomain.checked, + "elEntityHostTypeAvatar": elEntityHostTypeAvatar.checked + } + }; + EventBridge.emitWebEvent(JSON.stringify(message)); +} + +function loadDataInUi(importUiPersistedData) { + elJsonUrl.value = importUiPersistedData.elJsonUrl; + elImportAtAvatar.checked = importUiPersistedData.elImportAtAvatar; + elImportAtSpecificPosition.checked = importUiPersistedData.elImportAtSpecificPosition; + elPositionX.value = importUiPersistedData.elPositionX; + elPositionY.value = importUiPersistedData.elPositionY; + elPositionZ.value = importUiPersistedData.elPositionZ; + elEntityHostTypeDomain.checked = importUiPersistedData.elEntityHostTypeDomain; + elEntityHostTypeAvatar.checked = importUiPersistedData.elEntityHostTypeAvatar; + if (elImportAtSpecificPosition.checked) { + elImportAtSpecificPositionContainer.style.display = "Block"; + } +} + +function importJsonToWorld() { + elMessageContainer.innerHTML = ""; + + if (elJsonUrl.value === "") { + elMessageContainer.innerHTML = "
ERROR: 'URL/File (.json)' is required.
"; + return; + } + + let positioningMode = getRadioValue("importAtPosition"); + let entityHostType = getRadioValue("entityHostType"); + + if (positioningMode === "position" && (elPositionX.value === "" || elPositionY.value === "" || elPositionZ.value === "")) { + elMessageContainer.innerHTML = "
ERROR: 'Position' is required.
"; + return; + } + let position = {"x": parseFloat(elPositionX.value), "y": parseFloat(elPositionY.value), "z": parseFloat(elPositionZ.value)}; + let message = { + "type": "importUiImport", + "jsonURL": elJsonUrl.value, + "positioningMode": positioningMode, + "position": position, + "entityHostType": entityHostType + }; + EventBridge.emitWebEvent(JSON.stringify(message)); +} + +function getRadioValue(objectName) { + let radios = document.getElementsByName(objectName); + let i; + let selectedValue = ""; + for (i = 0; i < radios.length; i++) { + if (radios[i].checked) { + selectedValue = radios[i].value; + break; + } + } + return selectedValue; +} + +EventBridge.scriptEventReceived.connect(function(message){ + let messageObj = JSON.parse(message); + if (messageObj.type === "importUi_IMPORT_CONFIRMATION") { + elMessageContainer.innerHTML = "
IMPORT SUCCESSFUL.
"; + } else if (messageObj.type === "importUi_IMPORT_ERROR") { + elMessageContainer.innerHTML = "
IMPORT ERROR: " + messageObj.reason + "
"; + } else if (messageObj.type === "importUi_SELECTED_FILE") { + elJsonUrl.value = messageObj.file; + persistData(); + } else if (messageObj.type === "importUi_POSITION_TO_PASTE") { + elPositionX.value = messageObj.position.x; + elPositionY.value = messageObj.position.y; + elPositionZ.value = messageObj.position.z; + persistData(); + } else if (messageObj.type === "importUi_LOAD_DATA") { + loadDataInUi(messageObj.importUiPersistedData); + } +}); diff --git a/scripts/system/create/qml/EditTabView.qml b/scripts/system/create/qml/EditTabView.qml index 96e66c109e..2db23ec659 100644 --- a/scripts/system/create/qml/EditTabView.qml +++ b/scripts/system/create/qml/EditTabView.qml @@ -301,6 +301,22 @@ TabBar { } } + EditTabButton { + title: "IMPORT" + active: true + enabled: true + property string originalUrl: "" + + property Component visualItem: Component { + WebView { + id: advancedImportWebView + url: Qt.resolvedUrl("../importEntities/html/importEntities.html") + enabled: true + blurOnCtrlShift: false + } + } + } + function fromScript(message) { switch (message.method) { case 'selectTab': @@ -333,6 +349,9 @@ TabBar { case 'grid': editTabView.currentIndex = 3; break; + case 'import': + editTabView.currentIndex = 4; + break; default: console.warn('Attempt to switch to invalid tab:', id); } diff --git a/scripts/system/create/qml/EditToolsTabView.qml b/scripts/system/create/qml/EditToolsTabView.qml index 998c3a3aac..1000724458 100644 --- a/scripts/system/create/qml/EditToolsTabView.qml +++ b/scripts/system/create/qml/EditToolsTabView.qml @@ -291,6 +291,22 @@ TabBar { } } + EditTabButton { + title: "IMPORT" + active: true + enabled: true + property string originalUrl: "" + + property Component visualItem: Component { + WebView { + id: advancedImportWebView + url: Qt.resolvedUrl("../importEntities/html/importEntities.html") + enabled: true + blurOnCtrlShift: false + } + } + } + function fromScript(message) { switch (message.method) { case 'selectTab': @@ -304,7 +320,7 @@ TabBar { // Changes the current tab based on tab index or title as input function selectTab(id) { if (typeof id === 'number') { - if (id >= tabIndex.create && id <= tabIndex.grid) { + if (id >= tabIndex.create && id <= tabIndex.import) { editTabView.currentIndex = id; } else { console.warn('Attempt to switch to invalid tab:', id); @@ -320,6 +336,9 @@ TabBar { case 'grid': editTabView.currentIndex = tabIndex.grid; break; + case 'import': + editTabView.currentIndex = tabIndex.import; + break; default: console.warn('Attempt to switch to invalid tab:', id); } diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 70696abdab..f22692d7fb 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1,10 +1,10 @@ /* // edit-style.css // -// Created by Ryan Huffman on 13 Nov 2014 +// Created by Ryan Huffman on November 13th, 2014 // Copyright 2014 High Fidelity, Inc. // Copyright 2020 Vircadia contributors. -// Copyright 2022 Overte e.V. +// Copyright 2022-2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -701,6 +701,17 @@ div.section-header, hr { align-items: center; } +div.simpleSeparator { + width: 97%; + height: 2px; + border: 0px; + margin-top: 4px; + margin-right: 8px; + margin-left: 8px; + margin-bottom: 4px; + background-color: #777777; +} + .section.minor { margin: 0 21px; box-shadow: 1px -1px 0 rgb(37,37,37); @@ -1304,6 +1315,27 @@ div#grid-section, body#entity-list-body { margin: 0px 8px 8px 8px; } +#voxels-section { + padding-bottom: 0px; + margin: 8px 8px 8px 8px; +} + +#mode-section { + padding: 3px; + height: 28px; + margin: 8px 8px 8px 8px; + color: #000000; + background-color: #999999; + font-family: Raleway-Bold; + font-size: 16px; + border-radius: 5px; +} +#creationModeLabel { + padding-top: 4px; + width: 156px; +} + + #entity-list-header { margin-bottom: 6px; } @@ -1433,6 +1465,11 @@ input[type=button].entity-list-menutitle { background: linear-gradient(#343434 30%, #000 100%); cursor: pointer; } + +#voxel-edit-mode { + width: 120px; +} + input[type=button].entity-list-menutitle:enabled:hover { background: linear-gradient(#000, #000); border: none; @@ -2082,10 +2119,10 @@ div.entity-list-menu { div.tools-select-menu { position: relative; display: none; - width: 370px; + width: 200px; height: 0px; - top: 0px; - left: 8px; + top: -16px; + left: 124px; right: 0; bottom: 0; border-style: solid; @@ -2097,20 +2134,19 @@ div.tools-select-menu { } div.tools-help-popup { - font-family: FiraSans-SemiBold; - font-size: 15px; + font-family: Raleway-SemiBold; + font-size: 14px; position: relative; display: none; - width: 690px; + width: 96%; + padding: 5px; height: auto; - top: 0px; + top: -16px; left: 8px; right: 0; bottom: 0; - border-style: solid; - border-color: #505050; - border-width: 1px; - background-color: #404040; + border: 2px solid #c0c0c0; + background-color: #333333; z-index: 2; cursor: pointer; } diff --git a/scripts/system/html/gridControls.html b/scripts/system/html/gridControls.html index f752ec4f2a..e8cb643e46 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/html/gridControls.html @@ -1,9 +1,9 @@