diff options
Diffstat (limited to 'src/Authoring/Qt3DStudio/Render/StudioWidget.cpp')
-rw-r--r-- | src/Authoring/Qt3DStudio/Render/StudioWidget.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/src/Authoring/Qt3DStudio/Render/StudioWidget.cpp b/src/Authoring/Qt3DStudio/Render/StudioWidget.cpp new file mode 100644 index 00000000..cccce4d4 --- /dev/null +++ b/src/Authoring/Qt3DStudio/Render/StudioWidget.cpp @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "Qt3DSCommonPrecompile.h" +#include "StudioWidget.h" +#include "Qt3DSRenderWidgets.h" +#include "Qt3DSRenderContextCore.h" +#include "render/Qt3DSRenderContext.h" +#include "foundation/Qt3DSContainers.h" +#include "Qt3DSRenderShaderCodeGeneratorV2.h" + +using namespace qt3ds::widgets; + +void IStudioWidget::CreateRect(QT3DSVec3 rectStart, QT3DSVec3 rectEnd, QT3DSVec3 orth1, QT3DSF32 axisHalfWidth, + QT3DSF32 inColorIndex, TResultVecType &outResult) +{ + outResult.push_back(QT3DSVec4(rectStart + orth1 * axisHalfWidth, inColorIndex)); + outResult.push_back(QT3DSVec4(rectEnd + orth1 * axisHalfWidth, inColorIndex)); + outResult.push_back(QT3DSVec4(rectEnd - orth1 * axisHalfWidth, inColorIndex)); + outResult.push_back(QT3DSVec4(rectEnd - orth1 * axisHalfWidth, inColorIndex)); + outResult.push_back(QT3DSVec4(rectStart - orth1 * axisHalfWidth, inColorIndex)); + outResult.push_back(QT3DSVec4(rectStart + orth1 * axisHalfWidth, inColorIndex)); +} + +void IStudioWidget::CreateTriangle(QT3DSVec3 triStart, QT3DSVec3 triEnd, QT3DSVec3 orth1, QT3DSF32 triHalfWidth, + QT3DSF32 inColorIndex, TResultVecType &outResult) +{ + outResult.push_back(QT3DSVec4(triStart + orth1 * triHalfWidth, inColorIndex)); + outResult.push_back(QT3DSVec4(triStart - orth1 * triHalfWidth, inColorIndex)); + outResult.push_back(QT3DSVec4(triEnd, inColorIndex)); +} + +NVRenderInputAssembler *IStudioWidget::CreateRingedDisc( + NVAllocatorCallback &inAllocator, IRenderWidgetContext &inWidgetContext, + NVRenderContext &inRenderContext, QT3DSVec3 inDirection, QT3DSVec3 inCenterPt, QT3DSF32 inInnerRadius, + QT3DSF32 inOuterRadius, QT3DSF32 inDiscColor, QT3DSF32 inRingColor, const char *inItemName) +{ + CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inItemName); + NVRenderInputAssembler *retval = inWidgetContext.GetInputAssembler(theItemName); + if (retval) { + return retval; + } + TResultVecType theVertexData(inAllocator, "STranslationWidget::theVertexData"); + QT3DS_ASSERT(inInnerRadius < inOuterRadius); + QT3DSI32 numSubDivisions = 50; + QT3DSF32 arcRad = 360.0f / (QT3DSF32)numSubDivisions; + TORAD(arcRad); + QT3DSVec3 tempCross = inDirection.cross(QT3DSVec3(0, 1, 0)); + if (tempCross.magnitudeSquared() < .05f) + tempCross = inDirection.cross(QT3DSVec3(1, 0, 0)); + + QT3DSVec3 upDir = inDirection.cross(tempCross); + QT3DSVec3 leftDir = upDir.cross(inDirection); + upDir.normalize(); + leftDir.normalize(); + + for (QT3DSI32 idx = 0, numLooper = numSubDivisions; idx < numLooper; ++idx) { + QT3DSF32 startDeg = idx * 360.0f / numSubDivisions; + QT3DSF32 endDeg = (idx + 1) * 360.0f / numSubDivisions; + QT3DSF32 startRad(startDeg); + QT3DSF32 endRad(endDeg); + TORAD(startRad); + TORAD(endRad); + QT3DSF32 startSin = NVSin(startRad); + QT3DSF32 endSin = NVSin(endRad); + QT3DSF32 startCos = NVCos(startRad); + QT3DSF32 endCos = NVCos(endRad); + + QT3DSVec3 startDir = startSin * upDir + startCos * leftDir; + QT3DSVec3 endDir = endSin * upDir + endCos * leftDir; + + QT3DSVec3 discStart = inCenterPt + startDir * inInnerRadius; + QT3DSVec3 discEnd = inCenterPt + endDir * inInnerRadius; + QT3DSVec3 ringStart = inCenterPt + startDir * inOuterRadius; + QT3DSVec3 ringEnd = inCenterPt + endDir * inOuterRadius; + + // Create the Triangles + // disc first + theVertexData.push_back(QT3DSVec4(inCenterPt, inDiscColor)); + theVertexData.push_back(QT3DSVec4(discStart, inDiscColor)); + theVertexData.push_back(QT3DSVec4(discEnd, inDiscColor)); + + // Now two tris for the ring + theVertexData.push_back(QT3DSVec4(discStart, inRingColor)); + theVertexData.push_back(QT3DSVec4(ringStart, inRingColor)); + theVertexData.push_back(QT3DSVec4(ringEnd, inRingColor)); + theVertexData.push_back(QT3DSVec4(ringEnd, inRingColor)); + theVertexData.push_back(QT3DSVec4(discEnd, inRingColor)); + theVertexData.push_back(QT3DSVec4(discStart, inRingColor)); + } + + QT3DSU32 stride; + QT3DSU32 offset = 0; + NVRenderAttribLayout *theAttribLayout = &inWidgetContext.CreateAttributeLayout( + IStudioWidget::GetVertexBufferAttributesAndStride(stride)); + NVRenderVertexBuffer *theVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer( + theItemName, stride, toU8DataRef(theVertexData.begin(), theVertexData.size())); + + retval = &inWidgetContext.GetOrCreateInputAssembler( + theItemName, theAttribLayout, toConstDataRef(&theVertexBuffer, 1), nullptr, + toConstDataRef(&stride, 1), toConstDataRef(&offset, 1)); + + return retval; +} + +// Create an axis with a triangle at the top. Really we create two axis that are orthogonal to each +// other. +NVRenderInputAssembler * +IStudioWidget::CreateAxis(NVAllocatorCallback &inAllocator, IRenderWidgetContext &inWidgetContext, + NVRenderContext &inRenderContext, const QT3DSVec3 &inAxisDirection, + QT3DSF32 inAxisStartOffset, QT3DSF32 inAxisLength, QT3DSF32 inTriLength, + QT3DSF32 inAxisWidth, QT3DSF32 inTriWidth, const char *inAxisName) +{ + CRegisteredString theItemName = inRenderContext.GetStringTable().RegisterStr(inAxisName); + NVRenderInputAssembler *retval = inWidgetContext.GetInputAssembler(theItemName); + if (retval) { + return retval; + } + + TResultVecType theVertexData(inAllocator, "STranslationWidget::theVertexData"); + QT3DSVec3 orth1 = inAxisDirection.cross(QT3DSVec3(0, 0, 1)); + if (orth1.magnitudeSquared() < .05f) + orth1 = inAxisDirection.cross(QT3DSVec3(0, 1, 0)); + QT3DSVec3 orth2 = inAxisDirection.cross(orth1); + + // Draw a rect that starts at inAxisStartOffset + QT3DSVec3 rectStart = inAxisDirection * inAxisStartOffset; + // Rect end is also tri start, obviously + QT3DSVec3 rectEnd = inAxisDirection * (inAxisStartOffset + inAxisLength); + QT3DSVec3 triEnd = inAxisDirection * (inAxisStartOffset + inAxisLength + inTriLength); + + QT3DSF32 axisHalfWidth = inAxisWidth / 2.0f; + QT3DSF32 triHalfWidth = inTriWidth / 2.0f; + CreateRect(rectStart, rectEnd, orth1, axisHalfWidth, 0.0f, theVertexData); + CreateTriangle(rectEnd, triEnd, orth1, triHalfWidth, 0.0f, theVertexData); + CreateRect(rectStart, rectEnd, orth2, axisHalfWidth, 0.0f, theVertexData); + CreateTriangle(rectEnd, triEnd, orth2, triHalfWidth, 0.0f, theVertexData); + + QT3DSU32 stride; + QT3DSU32 offset = 0; + NVRenderAttribLayout *theAttribLayout = &inWidgetContext.CreateAttributeLayout( + IStudioWidget::GetVertexBufferAttributesAndStride(stride)); + NVRenderVertexBuffer *theVertexBuffer = &inWidgetContext.GetOrCreateVertexBuffer( + theItemName, stride, toU8DataRef(theVertexData.begin(), theVertexData.size())); + + retval = &inWidgetContext.GetOrCreateInputAssembler( + theItemName, theAttribLayout, toConstDataRef(&theVertexBuffer, 1), nullptr, + toConstDataRef(&stride, 1), toConstDataRef(&offset, 1)); + + return retval; +}; + +SWidgetRenderSetupResult::SWidgetRenderSetupResult(IRenderWidgetContext &inWidgetContext, + SNode &inNode, + RenderWidgetModes::Enum inWidgetMode) +{ + m_WidgetInfo = + inWidgetContext.GetWidgetRenderInformation(inNode, QT3DSVec3(0, 0, 0), inWidgetMode); + QT3DSMat44 theTranslationScale(QT3DSMat44::createIdentity()); + QT3DSMat33 theRotationMult(QT3DSMat33::createIdentity()); + bool includeNodeRotation = inWidgetMode == RenderWidgetModes::Local ? true : false; + if (includeNodeRotation) { + QT3DSMat44 theNodeRotation; + inNode.CalculateRotationMatrix(theNodeRotation); + if (inNode.m_Flags.IsLeftHanded()) { + SNode::FlipCoordinateSystem(theNodeRotation); + } + theRotationMult = + QT3DSMat33(theNodeRotation.column0.getXYZ(), theNodeRotation.column1.getXYZ(), + theNodeRotation.column2.getXYZ()); + } + + QT3DSMat33 theRotationMatrix = m_WidgetInfo.m_NormalMatrix * theRotationMult; + QT3DSMat33 theScaleMatrix(QT3DSMat33::createIdentity()); + theScaleMatrix.column0[0] = m_WidgetInfo.m_Scale; + theScaleMatrix.column1[1] = m_WidgetInfo.m_Scale; + theScaleMatrix.column2[2] = m_WidgetInfo.m_Scale; + QT3DSMat33 theCombined = theRotationMatrix * theScaleMatrix; + theTranslationScale.column0 = QT3DSVec4(theCombined.column0, 0.0f); + theTranslationScale.column1 = QT3DSVec4(theCombined.column1, 0.0f); + theTranslationScale.column2 = QT3DSVec4(theCombined.column2, 0.0f); + theTranslationScale.column3.x = m_WidgetInfo.m_Position.x; + theTranslationScale.column3.y = m_WidgetInfo.m_Position.y; + theTranslationScale.column3.z = m_WidgetInfo.m_Position.z; + m_TranslationScale = theTranslationScale; + m_PureProjection = m_WidgetInfo.m_PureProjection; + + QT3DSMat44 theCameraTransScale(QT3DSMat44::createIdentity()); + theCameraTransScale.column0 = QT3DSVec4(m_WidgetInfo.m_LookAtMatrix.column0, 0.0f); + theCameraTransScale.column1 = QT3DSVec4(m_WidgetInfo.m_LookAtMatrix.column1, 0.0f); + theCameraTransScale.column2 = QT3DSVec4(m_WidgetInfo.m_LookAtMatrix.column2, 0.0f); + theCameraTransScale.column3.x = m_WidgetInfo.m_Position.x; + theCameraTransScale.column3.y = m_WidgetInfo.m_Position.y; + theCameraTransScale.column3.z = m_WidgetInfo.m_Position.z; + theCameraTransScale.column0[0] = m_WidgetInfo.m_Scale; + theCameraTransScale.column1[1] = m_WidgetInfo.m_Scale; + theCameraTransScale.column2[2] = m_WidgetInfo.m_Scale; + m_CameraTranslationScale = theCameraTransScale; + m_SetupResult = m_WidgetInfo.m_LayerProjection * theTranslationScale; +} + +CRegisteredString IStudioWidget::GetSharedShaderName(IStringTable &inStrTable) +{ + return inStrTable.RegisterStr("IStudioWidget Shader"); +} + +CRegisteredString IStudioWidget::GetSharedPickShaderName(IStringTable &inStrTable) +{ + return inStrTable.RegisterStr("IStudioWidget Pick Shader"); +} + +NVRenderShaderProgram *IStudioWidget::CreateWidgetShader(IRenderWidgetContext &inWidgetContext, + NVRenderContext &inRenderContext) +{ + CRegisteredString theSharedName(GetSharedShaderName(inRenderContext.GetStringTable())); + NVRenderShaderProgram *retval = inWidgetContext.GetShader(theSharedName); + if (retval) + return retval; + qt3ds::render::IShaderProgramGenerator &theGenerator(inWidgetContext.GetProgramGenerator()); + theGenerator.BeginProgram(); + qt3ds::render::IShaderStageGenerator &theVertexGenerator( + *theGenerator.GetStage(qt3ds::render::ShaderGeneratorStages::Vertex)); + qt3ds::render::IShaderStageGenerator &theFragmentGenerator( + *theGenerator.GetStage(qt3ds::render::ShaderGeneratorStages::Fragment)); + theVertexGenerator.AddIncoming("attr_pos", "vec3"); + theVertexGenerator.AddIncoming("attr_color_index", "float"); + theVertexGenerator.AddOutgoing("output_color_index", "float"); + theVertexGenerator.AddUniform("model_view_projection", "mat4"); + // These are required in order to scale the scale widget the way we want to scale it. + theVertexGenerator.AddUniform("attr_pos_add_start", "float"); + theVertexGenerator.AddUniform("attr_pos_add_amount", "vec3"); + theVertexGenerator.Append("void main() {"); + theVertexGenerator + << "\tvec3 thePos = attr_pos;" << Endl + << "\tif ( length(thePos) > attr_pos_add_start ) thePos = thePos + attr_pos_add_amount;" + << Endl; + theVertexGenerator.Append("\tgl_Position = model_view_projection * vec4(thePos, 1.0);"); + theVertexGenerator.Append("\toutput_color_index = attr_color_index;"); + theVertexGenerator.Append("}"); + theFragmentGenerator.AddUniform("color0", "vec3"); + theFragmentGenerator.AddUniform("color1", "vec3"); + theFragmentGenerator.Append("void main() {"); + theFragmentGenerator.Append("\tgl_FragColor.rgb = output_color_index > 0.0 ? color1 : color0;"); + theFragmentGenerator.Append("\tgl_FragColor.a = 1.0;"); + theFragmentGenerator.Append("}"); + return inWidgetContext.CompileAndStoreShader(theSharedName); +} + +NVRenderShaderProgram *IStudioWidget::CreateWidgetPickShader(IRenderWidgetContext &inWidgetContext, + NVRenderContext &inRenderContext) +{ + CRegisteredString theSharedName(GetSharedPickShaderName(inRenderContext.GetStringTable())); + NVRenderShaderProgram *retval = inWidgetContext.GetShader(theSharedName); + if (retval) + return retval; + qt3ds::render::IShaderProgramGenerator &theGenerator(inWidgetContext.GetProgramGenerator()); + theGenerator.BeginProgram(); + qt3ds::render::IShaderStageGenerator &theVertexGenerator( + *theGenerator.GetStage(qt3ds::render::ShaderGeneratorStages::Vertex)); + qt3ds::render::IShaderStageGenerator &theFragmentGenerator( + *theGenerator.GetStage(qt3ds::render::ShaderGeneratorStages::Fragment)); + theVertexGenerator.AddIncoming("attr_pos", "vec3"); + theVertexGenerator.AddUniform("model_view_projection", "mat4"); + theVertexGenerator.Append("void main() {"); + theVertexGenerator.Append("\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);"); + theVertexGenerator.Append("}"); + theFragmentGenerator.AddUniform("object_id", "int"); + theFragmentGenerator.Append("void main() {"); + if (inRenderContext.GetRenderContextType() == NVRenderContextValues::GLES2) { + theFragmentGenerator.Append("int moddiv = object_id / 256;"); + theFragmentGenerator.Append( + "\tgl_FragColor.r = float(object_id - moddiv * 256)/255.0;"); + } else { + theFragmentGenerator.Append("\tgl_FragColor.r = float(object_id % 256)/255.0;"); + } + theFragmentGenerator.Append("\tgl_FragColor.g = float(object_id / 256)/255.0;"); + theFragmentGenerator.Append("\tgl_FragColor.b = 0.0;"); + theFragmentGenerator.Append("\tgl_FragColor.a = 1.0;"); + theFragmentGenerator.Append("}"); + return inWidgetContext.CompileAndStoreShader(theSharedName); +} + +NVConstDataRef<qt3ds::render::NVRenderVertexBufferEntry> +IStudioWidget::GetVertexBufferAttributesAndStride(QT3DSU32 &stride) +{ + static qt3ds::render::NVRenderVertexBufferEntry theEntries[] = { + qt3ds::render::NVRenderVertexBufferEntry("attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, + 3), + qt3ds::render::NVRenderVertexBufferEntry("attr_color_index", + qt3ds::render::NVRenderComponentTypes::QT3DSF32, 1, 12), + }; + + stride = 3 * sizeof(QT3DSF32) + 1 * sizeof(QT3DSF32); + + return toConstDataRef(theEntries, 2); +} |