mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 12:14:00 +02:00
merge
This commit is contained in:
commit
a4b04d9d43
10 changed files with 187 additions and 141 deletions
|
@ -135,7 +135,4 @@ namespace scriptable {
|
|||
using ScriptableMeshPointer = QPointer<ScriptableMesh>;
|
||||
class ScriptableMeshPart;
|
||||
using ScriptableMeshPartPointer = QPointer<ScriptableMeshPart>;
|
||||
bool registerMetaTypes(QScriptEngine* engine);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(NestableType)
|
||||
|
|
|
@ -26,9 +26,6 @@
|
|||
#include <SpatiallyNestable.h>
|
||||
|
||||
GraphicsScriptingInterface::GraphicsScriptingInterface(QObject* parent) : QObject(parent), QScriptable() {
|
||||
if (auto scriptEngine = qobject_cast<QScriptEngine*>(parent)) {
|
||||
this->registerMetaTypes(scriptEngine);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScriptingInterface::jsThrowError(const QString& error) {
|
||||
|
@ -179,12 +176,17 @@ scriptable::ScriptableMeshPointer GraphicsScriptingInterface::newMesh(const QVar
|
|||
|
||||
const auto numVertices = vertices.size();
|
||||
const auto numIndices = indices.size();
|
||||
const auto topology = graphics::Mesh::TRIANGLES;
|
||||
const auto topology = graphics::TOPOLOGIES.key(topologyName);
|
||||
|
||||
// TODO: support additional topologies (POINTS and LINES ought to "just work" --
|
||||
// if MeshPartPayload::drawCall is updated to actually check the Mesh::Part::_topology value
|
||||
// (TRIANGLE_STRIP, TRIANGLE_FAN, QUADS, QUAD_STRIP may need additional conversion code though)
|
||||
static const QStringList acceptableTopologies{ "triangles" };
|
||||
|
||||
// sanity checks
|
||||
QString error;
|
||||
if (!topologyName.isEmpty() && topologyName != "triangles") {
|
||||
error = "expected 'triangles' or undefined for .topology";
|
||||
if (!topologyName.isEmpty() && !acceptableTopologies.contains(topologyName)) {
|
||||
error = QString("expected .topology to be %1").arg(acceptableTopologies.join(" | "));
|
||||
} else if (!numIndices) {
|
||||
error = QString("expected non-empty [uint32,...] array for .indices (got type=%1)").arg(ifsMeshData.value("indices").typeName());
|
||||
} else if (numIndices % 3 != 0) {
|
||||
|
@ -227,8 +229,8 @@ scriptable::ScriptableMeshPointer GraphicsScriptingInterface::newMesh(const QVar
|
|||
mesh->modelName = "graphics::newMesh";
|
||||
mesh->displayName = meshName.toStdString();
|
||||
|
||||
// TODO: newFromVector does no conversion -- later we could autodetect if fitting into gpu::INDEX_UINT16
|
||||
// and also pack other values (like NORMAL / TEXCOORD0 where relevant)
|
||||
// TODO: newFromVector does inbound type conversion, but not compression or packing
|
||||
// (later we should autodetect if fitting into gpu::INDEX_UINT16 and reduce / pack normals etc.)
|
||||
mesh->setIndexBuffer(buffer_helpers::newFromVector(indices, gpu::Format::INDEX_INT32));
|
||||
mesh->setVertexBuffer(buffer_helpers::newFromVector(vertices, gpu::Format::VEC3F_XYZ));
|
||||
if (normals.size()) {
|
||||
|
@ -240,7 +242,7 @@ scriptable::ScriptableMeshPointer GraphicsScriptingInterface::newMesh(const QVar
|
|||
if (texCoords0.size()) {
|
||||
mesh->addAttribute(gpu::Stream::TEXCOORD0, buffer_helpers::newFromVector(texCoords0, gpu::Format::VEC2F_UV));
|
||||
}
|
||||
QVector<graphics::Mesh::Part> parts = {{ 0, indices.size(), 0, topology}};
|
||||
QVector<graphics::Mesh::Part> parts = {{ 0, indices.size(), 0, topology }};
|
||||
mesh->setPartBuffer(buffer_helpers::newFromVector(parts, gpu::Element::PART_DRAWCALL));
|
||||
return scriptable::make_scriptowned<scriptable::ScriptableMesh>(mesh, nullptr);
|
||||
}
|
||||
|
@ -262,10 +264,6 @@ QString GraphicsScriptingInterface::exportModelToOBJ(const scriptable::Scriptabl
|
|||
return QString();
|
||||
}
|
||||
|
||||
void GraphicsScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
|
||||
scriptable::registerMetaTypes(engine);
|
||||
}
|
||||
|
||||
MeshPointer GraphicsScriptingInterface::getMeshPointer(const scriptable::ScriptableMesh& meshProxy) {
|
||||
return meshProxy.getMeshPointer();
|
||||
}
|
||||
|
@ -287,12 +285,57 @@ MeshPointer GraphicsScriptingInterface::getMeshPointer(scriptable::ScriptableMes
|
|||
}
|
||||
|
||||
namespace {
|
||||
QScriptValue qVectorUInt32ToScriptValue(QScriptEngine* engine, const QVector<glm::uint32>& vector) {
|
||||
return qScriptValueFromSequence(engine, vector);
|
||||
}
|
||||
QVector<int> metaTypeIds{
|
||||
qRegisterMetaType<glm::uint32>("uint32"),
|
||||
qRegisterMetaType<glm::uint32>("glm::uint32"),
|
||||
qRegisterMetaType<QVector<glm::uint32>>(),
|
||||
qRegisterMetaType<QVector<glm::uint32>>("QVector<uint32>"),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshes>(),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshes>("ScriptableMeshes"),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshes>("scriptable::ScriptableMeshes"),
|
||||
qRegisterMetaType<QVector<scriptable::ScriptableMeshPointer>>("QVector<scriptable::ScriptableMeshPointer>"),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshPointer>(),
|
||||
qRegisterMetaType<scriptable::ScriptableModelPointer>(),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshPartPointer>(),
|
||||
qRegisterMetaType<scriptable::ScriptableMaterial>(),
|
||||
qRegisterMetaType<QVector<scriptable::ScriptableMaterial>>(),
|
||||
qRegisterMetaType<scriptable::MultiMaterialMap>(),
|
||||
qRegisterMetaType<graphics::Mesh::Topology>(),
|
||||
};
|
||||
}
|
||||
|
||||
void qVectorUInt32FromScriptValue(const QScriptValue& array, QVector<glm::uint32>& result) {
|
||||
qScriptValueToSequence(array, result);
|
||||
namespace scriptable {
|
||||
template <typename T> int registerQPointerMetaType(QScriptEngine* engine) {
|
||||
qScriptRegisterSequenceMetaType<QVector<QPointer<T>>>(engine);
|
||||
return qScriptRegisterMetaType<QPointer<T>>(
|
||||
engine,
|
||||
[](QScriptEngine* engine, const QPointer<T>& object) -> QScriptValue {
|
||||
if (!object) {
|
||||
return QScriptValue::NullValue;
|
||||
}
|
||||
return engine->newQObject(object, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::AutoCreateDynamicProperties);
|
||||
},
|
||||
[](const QScriptValue& value, QPointer<T>& out) {
|
||||
auto obj = value.toQObject();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "qpointer_qobject_cast" << obj << value.toString();
|
||||
#endif
|
||||
if (auto tmp = qobject_cast<T*>(obj)) {
|
||||
out = QPointer<T>(tmp);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
if (auto tmp = static_cast<T*>(obj)) {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "qpointer_qobject_cast -- via static_cast" << obj << tmp << value.toString();
|
||||
#endif
|
||||
out = QPointer<T>(tmp);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
out = nullptr;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
QScriptValue qVectorScriptableMaterialToScriptValue(QScriptEngine* engine, const QVector<scriptable::ScriptableMaterial>& vector) {
|
||||
|
@ -346,102 +389,38 @@ namespace {
|
|||
// No need to convert from QScriptValue to MultiMaterialMap
|
||||
}
|
||||
|
||||
QVector<int> metaTypeIds{
|
||||
qRegisterMetaType<glm::uint32>("uint32"),
|
||||
qRegisterMetaType<glm::uint32>("glm::uint32"),
|
||||
qRegisterMetaType<QVector<glm::uint32>>(),
|
||||
qRegisterMetaType<QVector<glm::uint32>>("QVector<uint32>"),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshes>(),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshes>("ScriptableMeshes"),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshes>("scriptable::ScriptableMeshes"),
|
||||
qRegisterMetaType<QVector<scriptable::ScriptableMeshPointer>>("QVector<scriptable::ScriptableMeshPointer>"),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshPointer>(),
|
||||
qRegisterMetaType<scriptable::ScriptableModelPointer>(),
|
||||
qRegisterMetaType<scriptable::ScriptableMeshPartPointer>(),
|
||||
qRegisterMetaType<scriptable::ScriptableMaterial>(),
|
||||
qRegisterMetaType<QVector<scriptable::ScriptableMaterial>>(),
|
||||
qRegisterMetaType<scriptable::MultiMaterialMap>(),
|
||||
qRegisterMetaType<graphics::Mesh::Topology>(),
|
||||
};
|
||||
}
|
||||
|
||||
namespace scriptable {
|
||||
template <typename T> int registerQPointerThing(QScriptEngine* engine) {
|
||||
qScriptRegisterSequenceMetaType<QVector<QPointer<T>>>(engine);
|
||||
return qScriptRegisterMetaType<QPointer<T>>(
|
||||
engine,
|
||||
[](QScriptEngine* engine, const QPointer<T>& object) -> QScriptValue {
|
||||
if (!object) {
|
||||
return QScriptValue::NullValue;
|
||||
}
|
||||
return engine->newQObject(object, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::AutoCreateDynamicProperties);
|
||||
},
|
||||
[](const QScriptValue& value, QPointer<T>& out) {
|
||||
auto obj = value.toQObject();
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "qpointer_qobject_cast" << obj << value.toString();
|
||||
#endif
|
||||
if (auto tmp = qobject_cast<T*>(obj)) {
|
||||
out = QPointer<T>(tmp);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
if (auto tmp = static_cast<T*>(obj)) {
|
||||
#ifdef SCRIPTABLE_MESH_DEBUG
|
||||
qCInfo(graphics_scripting) << "qpointer_qobject_cast -- via static_cast" << obj << tmp << value.toString();
|
||||
#endif
|
||||
out = QPointer<T>(tmp);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
out = nullptr;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
template <typename T> int registerDebugEnum(QScriptEngine* engine, const DebugEnums<T>& debugEnums) {
|
||||
static const DebugEnums<T>& poop = debugEnums;
|
||||
static const DebugEnums<T>& instance = debugEnums;
|
||||
return qScriptRegisterMetaType<T>(
|
||||
engine,
|
||||
[](QScriptEngine* engine, const T& topology) -> QScriptValue {
|
||||
return poop.value(topology);
|
||||
return instance.value(topology);
|
||||
},
|
||||
[](const QScriptValue& value, T& topology) {
|
||||
topology = poop.key(value.toString());
|
||||
topology = instance.key(value.toString());
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool registerMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterSequenceMetaType<QVector<glm::uint32>>(engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<scriptable::ScriptableMaterial>>(engine);
|
||||
void GraphicsScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterSequenceMetaType<QVector<glm::uint32>>(engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<scriptable::ScriptableMaterial>>(engine);
|
||||
|
||||
qScriptRegisterMetaType(engine, qVectorUInt32ToScriptValue, qVectorUInt32FromScriptValue);
|
||||
scriptable::registerQPointerMetaType<scriptable::ScriptableModel>(engine);
|
||||
scriptable::registerQPointerMetaType<scriptable::ScriptableMesh>(engine);
|
||||
scriptable::registerQPointerMetaType<scriptable::ScriptableMeshPart>(engine);
|
||||
|
||||
registerQPointerThing<scriptable::ScriptableModel>(engine);
|
||||
registerQPointerThing<scriptable::ScriptableMesh>(engine);
|
||||
registerQPointerThing<scriptable::ScriptableMeshPart>(engine);
|
||||
qScriptRegisterMetaType<QVector<scriptable::ScriptableMeshPointer>>(
|
||||
engine,
|
||||
[](QScriptEngine* engine, const QVector<scriptable::ScriptableMeshPointer>& vector) -> QScriptValue {
|
||||
return qScriptValueFromSequence(engine, vector);
|
||||
},
|
||||
[](const QScriptValue& array, QVector<scriptable::ScriptableMeshPointer>& result) {
|
||||
qScriptValueToSequence(array, result);
|
||||
}
|
||||
);
|
||||
qScriptRegisterMetaType(engine, scriptableMaterialToScriptValue, scriptableMaterialFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, qVectorScriptableMaterialToScriptValue, qVectorScriptableMaterialFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, multiMaterialMapToScriptValue, multiMaterialMapFromScriptValue);
|
||||
scriptable::registerDebugEnum<graphics::Mesh::Topology>(engine, graphics::TOPOLOGIES);
|
||||
scriptable::registerDebugEnum<gpu::Type>(engine, gpu::TYPES);
|
||||
scriptable::registerDebugEnum<gpu::Semantic>(engine, gpu::SEMANTICS);
|
||||
scriptable::registerDebugEnum<gpu::Dimension>(engine, gpu::DIMENSIONS);
|
||||
|
||||
registerDebugEnum<graphics::Mesh::Topology>(engine, graphics::TOPOLOGIES);
|
||||
registerDebugEnum<gpu::Type>(engine, gpu::TYPES);
|
||||
registerDebugEnum<gpu::Semantic>(engine, gpu::SEMANTICS);
|
||||
registerDebugEnum<gpu::Dimension>(engine, gpu::DIMENSIONS);
|
||||
|
||||
return metaTypeIds.size();
|
||||
}
|
||||
qScriptRegisterMetaType(engine, scriptable::scriptableMaterialToScriptValue, scriptable::scriptableMaterialFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, scriptable::qVectorScriptableMaterialToScriptValue, scriptable::qVectorScriptableMaterialFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, scriptable::multiMaterialMapToScriptValue, scriptable::multiMaterialMapFromScriptValue);
|
||||
|
||||
Q_UNUSED(metaTypeIds);
|
||||
}
|
||||
|
||||
#include "GraphicsScriptingInterface.moc"
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
#include "ScriptableMesh.h"
|
||||
#include <DependencyManager.h>
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* The experimental Graphics API <em>(experimental)</em> lets you query and manage certain graphics-related structures (like underlying meshes and textures) from scripting.
|
||||
* @namespace Graphics
|
||||
*/
|
||||
|
||||
class GraphicsScriptingInterface : public QObject, public QScriptable, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -29,15 +35,36 @@ public:
|
|||
|
||||
public slots:
|
||||
/**jsdoc
|
||||
* Returns the model/meshes associated with a UUID (entityID, overlayID, or avatarID)
|
||||
* Returns a model reference object associated with the specified UUID ({@link EntityID}, {@link OverlayID}, or {@link AvatarID}).
|
||||
*
|
||||
* @function GraphicsScriptingInterface.getModel
|
||||
* @param {UUID} The objectID of the model whose meshes are to be retrieve
|
||||
* @function Graphics.getModel
|
||||
* @param {UUID} The objectID of the model whose meshes are to be retrieved.
|
||||
* @return {Graphics.Model} the resulting Model object
|
||||
*/
|
||||
scriptable::ScriptableModelPointer getModel(QUuid uuid);
|
||||
|
||||
bool updateModel(QUuid uuid, const scriptable::ScriptableModelPointer& model);
|
||||
|
||||
bool canUpdateModel(QUuid uuid, int meshIndex = -1, int partNumber = -1);
|
||||
|
||||
scriptable::ScriptableModelPointer newModel(const scriptable::ScriptableMeshes& meshes);
|
||||
|
||||
/**jsdoc
|
||||
* Create a new Mesh / Mesh Part with the specified data buffers.
|
||||
*
|
||||
* @function Graphics.newMesh
|
||||
* @param {Graphics.IFSData} ifsMeshData Index-Faced Set (IFS) arrays used to create the new mesh.
|
||||
* @return {Graphics.Mesh} the resulting Mesh / Mesh Part object
|
||||
*/
|
||||
/**jsdoc
|
||||
* @typedef {object} Graphics.IFSData
|
||||
* @property {string} [name] - mesh name (useful for debugging / debug prints).
|
||||
* @property {number[]} indices - vertex indices to use for the mesh faces.
|
||||
* @property {Vec3[]} vertices - vertex positions (model space)
|
||||
* @property {Vec3[]} [normals] - vertex normals (normalized)
|
||||
* @property {Vec3[]} [colors] - vertex colors (normalized)
|
||||
* @property {Vec2[]} [texCoords0] - vertex texture coordinates (normalized)
|
||||
*/
|
||||
scriptable::ScriptableMeshPointer newMesh(const QVariantMap& ifsMeshData);
|
||||
|
||||
#ifdef SCRIPTABLE_MESH_TODO
|
||||
|
@ -58,6 +85,8 @@ private:
|
|||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(scriptable::ModelProviderPointer)
|
||||
Q_DECLARE_METATYPE(glm::uint32)
|
||||
Q_DECLARE_METATYPE(QVector<glm::uint32>)
|
||||
Q_DECLARE_METATYPE(NestableType)
|
||||
|
||||
#endif // hifi_GraphicsScriptingInterface_h
|
||||
|
|
|
@ -118,7 +118,7 @@ bool scriptable::ScriptableMesh::setVertexAttributes(glm::uint32 vertexIndex, co
|
|||
return buffer_helpers::mesh::setVertexAttributes(getMeshPointer(), vertexIndex, attributes);
|
||||
}
|
||||
|
||||
int scriptable::ScriptableMesh::_getSlotNumber(const QString& attributeName) const {
|
||||
int scriptable::ScriptableMesh::getSlotNumber(const QString& attributeName) const {
|
||||
if (auto mesh = getMeshPointer()) {
|
||||
return buffer_helpers::ATTRIBUTES.value(attributeName, -1);
|
||||
}
|
||||
|
@ -142,9 +142,9 @@ QVariantMap scriptable::ScriptableMesh::getBufferFormats() const {
|
|||
}
|
||||
|
||||
bool scriptable::ScriptableMesh::removeAttribute(const QString& attributeName) {
|
||||
auto slot = isValid() ? _getSlotNumber(attributeName) : -1;
|
||||
auto slot = isValid() ? getSlotNumber(attributeName) : -1;
|
||||
if (slot < 0) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
if (slot == gpu::Stream::POSITION) {
|
||||
context()->throwError("cannot remove .position attribute");
|
||||
|
@ -158,7 +158,7 @@ bool scriptable::ScriptableMesh::removeAttribute(const QString& attributeName) {
|
|||
}
|
||||
|
||||
glm::uint32 scriptable::ScriptableMesh::addAttribute(const QString& attributeName, const QVariant& defaultValue) {
|
||||
auto slot = isValid() ? _getSlotNumber(attributeName) : -1;
|
||||
auto slot = isValid() ? getSlotNumber(attributeName) : -1;
|
||||
if (slot < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ glm::uint32 scriptable::ScriptableMesh::addAttribute(const QString& attributeNam
|
|||
}
|
||||
|
||||
glm::uint32 scriptable::ScriptableMesh::fillAttribute(const QString& attributeName, const QVariant& value) {
|
||||
auto slot = isValid() ? _getSlotNumber(attributeName) : -1;
|
||||
auto slot = isValid() ? getSlotNumber(attributeName) : -1;
|
||||
if (slot < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ QVariantList scriptable::ScriptableMesh::queryVertexAttributes(QVariant selector
|
|||
if (!isValidIndex(0, attributeName)) {
|
||||
return result;
|
||||
}
|
||||
auto slotNum = _getSlotNumber(attributeName);
|
||||
auto slotNum = getSlotNumber(attributeName);
|
||||
const auto& bufferView = buffer_helpers::mesh::getBufferView(getMeshPointer(), static_cast<gpu::Stream::Slot>(slotNum));
|
||||
glm::uint32 numElements = (glm::uint32)bufferView.getNumElements();
|
||||
for (glm::uint32 i = 0; i < numElements; i++) {
|
||||
|
@ -231,7 +231,7 @@ QVariant scriptable::ScriptableMesh::getVertexProperty(glm::uint32 vertexIndex,
|
|||
if (!isValidIndex(vertexIndex, attributeName)) {
|
||||
return QVariant();
|
||||
}
|
||||
auto slotNum = _getSlotNumber(attributeName);
|
||||
auto slotNum = getSlotNumber(attributeName);
|
||||
const auto& bufferView = buffer_helpers::mesh::getBufferView(getMeshPointer(), static_cast<gpu::Stream::Slot>(slotNum));
|
||||
return buffer_helpers::getValue<QVariant>(bufferView, vertexIndex, qUtf8Printable(attributeName));
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ bool scriptable::ScriptableMesh::setVertexProperty(glm::uint32 vertexIndex, cons
|
|||
if (!isValidIndex(vertexIndex, attributeName)) {
|
||||
return false;
|
||||
}
|
||||
auto slotNum = _getSlotNumber(attributeName);
|
||||
auto slotNum = getSlotNumber(attributeName);
|
||||
const auto& bufferView = buffer_helpers::mesh::getBufferView(getMeshPointer(), static_cast<gpu::Stream::Slot>(slotNum));
|
||||
return buffer_helpers::setValue(bufferView, vertexIndex, value);
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ bool scriptable::ScriptableMesh::isValidIndex(glm::uint32 vertexIndex, const QSt
|
|||
return false;
|
||||
}
|
||||
if (!attributeName.isEmpty()) {
|
||||
auto slotNum = _getSlotNumber(attributeName);
|
||||
auto slotNum = getSlotNumber(attributeName);
|
||||
if (slotNum < 0) {
|
||||
if (context()) {
|
||||
context()->throwError(QString("invalid attributeName=%1").arg(attributeName));
|
||||
|
|
|
@ -28,6 +28,15 @@
|
|||
#include <graphics/Geometry.h>
|
||||
|
||||
namespace scriptable {
|
||||
/**jsdoc
|
||||
* @typedef {object} Graphics.Mesh
|
||||
* @property {Graphics.MeshPart[]} parts - Array of submesh part references.
|
||||
* @property {string[]} attributeNames - Vertex attribute names (color, normal, etc.)
|
||||
* @property {number} numParts - The number of parts contained in the mesh.
|
||||
* @property {number} numIndices - Total number of vertex indices in the mesh.
|
||||
* @property {number} numVertices - Total number of vertices in the Mesh.
|
||||
* @property {number} numAttributes - Number of currently defined vertex attributes.
|
||||
*/
|
||||
class ScriptableMesh : public ScriptableMeshBase, QScriptable {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -65,9 +74,8 @@ namespace scriptable {
|
|||
QVector<scriptable::ScriptableMeshPartPointer> getMeshParts() const;
|
||||
QVariantMap getMeshExtents() const;
|
||||
|
||||
// TODO: remove Q_INVOKABLE (curently exposed for debugging )
|
||||
Q_INVOKABLE int _getSlotNumber(const QString& attributeName) const;
|
||||
operator bool() const { return !weakMesh.expired(); }
|
||||
int getSlotNumber(const QString& attributeName) const;
|
||||
|
||||
public slots:
|
||||
const scriptable::ScriptableModelPointer getParentModel() const { return qobject_cast<scriptable::ScriptableModel*>(model); }
|
||||
|
@ -97,5 +105,3 @@ namespace scriptable {
|
|||
|
||||
Q_DECLARE_METATYPE(scriptable::ScriptableMeshPointer)
|
||||
Q_DECLARE_METATYPE(QVector<scriptable::ScriptableMeshPointer>)
|
||||
Q_DECLARE_METATYPE(glm::uint32)
|
||||
Q_DECLARE_METATYPE(QVector<glm::uint32>)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <graphics/GpuHelpers.h>
|
||||
#include <graphics/Geometry.h>
|
||||
|
||||
|
||||
QString scriptable::ScriptableMeshPart::toOBJ() {
|
||||
if (!getMeshPointer()) {
|
||||
if (context()) {
|
||||
|
@ -56,7 +57,7 @@ bool scriptable::ScriptableMeshPart::setVertexProperty(glm::uint32 vertexIndex,
|
|||
if (!isValidIndex(vertexIndex, attributeName)) {
|
||||
return false;
|
||||
}
|
||||
auto slotNum = parentMesh->_getSlotNumber(attributeName);
|
||||
auto slotNum = parentMesh->getSlotNumber(attributeName);
|
||||
const auto& bufferView = buffer_helpers::mesh::getBufferView(getMeshPointer(), static_cast<gpu::Stream::Slot>(slotNum));
|
||||
return buffer_helpers::setValue(bufferView, vertexIndex, value);
|
||||
}
|
||||
|
@ -368,9 +369,10 @@ bool scriptable::ScriptableMeshPart::setIndices(const QVector<glm::uint32>& indi
|
|||
return false;
|
||||
}
|
||||
glm::uint32 len = indices.size();
|
||||
if (len != getNumVertices()) {
|
||||
if (len != getNumIndices()) {
|
||||
context()->throwError(QString("setIndices: currently new indicies must be assign 1:1 across old indicies (indicies.size()=%1, numIndices=%2)")
|
||||
.arg(len).arg(getNumIndices()));
|
||||
return false;
|
||||
}
|
||||
auto mesh = getMeshPointer();
|
||||
auto indexBuffer = mesh->getIndexBuffer();
|
||||
|
@ -397,18 +399,24 @@ const graphics::Mesh::Part& scriptable::ScriptableMeshPart::getMeshPart() const
|
|||
return getMeshPointer()->getPartBuffer().get<graphics::Mesh::Part>(partIndex);
|
||||
}
|
||||
|
||||
// FIXME: how we handle topology will need to be reworked if wanting to support TRIANGLE_STRIP, QUADS and QUAD_STRIP
|
||||
bool scriptable::ScriptableMeshPart::setTopology(graphics::Mesh::Topology topology) {
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
auto& part = getMeshPointer()->getPartBuffer().edit<graphics::Mesh::Part>(partIndex);
|
||||
if (topology == graphics::Mesh::Topology::POINTS ||
|
||||
topology == graphics::Mesh::Topology::LINES ||
|
||||
topology == graphics::Mesh::Topology::TRIANGLES) {
|
||||
switch (topology) {
|
||||
#ifdef DEV_BUILD
|
||||
case graphics::Mesh::Topology::POINTS:
|
||||
case graphics::Mesh::Topology::LINES:
|
||||
#endif
|
||||
case graphics::Mesh::Topology::TRIANGLES:
|
||||
part._topology = topology;
|
||||
return true;
|
||||
default:
|
||||
context()->throwError("changing topology to " + graphics::toString(topology) + " is not yet supported");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::uint32 scriptable::ScriptableMeshPart::getTopologyLength() const {
|
||||
|
@ -416,16 +424,23 @@ glm::uint32 scriptable::ScriptableMeshPart::getTopologyLength() const {
|
|||
case graphics::Mesh::Topology::POINTS: return 1;
|
||||
case graphics::Mesh::Topology::LINES: return 2;
|
||||
case graphics::Mesh::Topology::TRIANGLES: return 3;
|
||||
case graphics::Mesh::Topology::QUADS: return 4;
|
||||
default: qCDebug(graphics_scripting) << "getTopologyLength -- unrecognized topology" << getTopology();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QVector<glm::uint32> scriptable::ScriptableMeshPart::getFace(glm::uint32 faceIndex) const {
|
||||
if (faceIndex < getNumFaces()) {
|
||||
return getIndices().mid(faceIndex * getTopologyLength(), getTopologyLength());
|
||||
switch (getTopology()) {
|
||||
case graphics::Mesh::Topology::POINTS:
|
||||
case graphics::Mesh::Topology::LINES:
|
||||
case graphics::Mesh::Topology::TRIANGLES:
|
||||
case graphics::Mesh::Topology::QUADS:
|
||||
if (faceIndex < getNumFaces()) {
|
||||
return getIndices().mid(faceIndex * getTopologyLength(), getTopologyLength());
|
||||
}
|
||||
default: return QVector<glm::uint32>();
|
||||
}
|
||||
return QVector<glm::uint32>();
|
||||
}
|
||||
|
||||
QVariantMap scriptable::ScriptableMeshPart::getPartExtents() const {
|
||||
|
|
|
@ -10,6 +10,18 @@
|
|||
#include "ScriptableMesh.h"
|
||||
|
||||
namespace scriptable {
|
||||
/**jsdoc
|
||||
* @typedef {object} Graphics.MeshPart
|
||||
* @property {number} partIndex - The part index (within the containing Mesh).
|
||||
* @property {Graphics.Topology} topology - element interpretation (currently only 'triangles' is supported).
|
||||
* @property {string[]} attributeNames - Vertex attribute names (color, normal, etc.)
|
||||
* @property {number} numIndices - Number of vertex indices that this mesh part refers to.
|
||||
* @property {number} numVerticesPerFace - Number of vertices per face (eg: 3 when topology is 'triangles').
|
||||
* @property {number} numFaces - Number of faces represented by the mesh part (numIndices / numVerticesPerFace).
|
||||
* @property {number} numVertices - Total number of vertices in the containing Mesh.
|
||||
* @property {number} numAttributes - Number of currently defined vertex attributes.
|
||||
*/
|
||||
|
||||
class ScriptableMeshPart : public QObject, QScriptable {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool valid READ isValid)
|
||||
|
@ -18,7 +30,8 @@ namespace scriptable {
|
|||
Q_PROPERTY(glm::uint32 baseVertexIndex READ getBaseVertexIndex WRITE setBaseVertexIndex)
|
||||
Q_PROPERTY(glm::uint32 lastVertexIndex READ getLastVertexIndex WRITE setLastVertexIndex)
|
||||
Q_PROPERTY(int numVerticesPerFace READ getTopologyLength)
|
||||
Q_PROPERTY(graphics::Mesh::Topology topology READ getTopology WRITE setTopology)
|
||||
// NOTE: making read-only for now (see also GraphicsScriptingInterface::newMesh and MeshPartPayload::drawCall)
|
||||
Q_PROPERTY(graphics::Mesh::Topology topology READ getTopology)
|
||||
|
||||
Q_PROPERTY(glm::uint32 numFaces READ getNumFaces)
|
||||
Q_PROPERTY(glm::uint32 numAttributes READ getNumAttributes)
|
||||
|
|
|
@ -15,6 +15,14 @@ class QScriptValue;
|
|||
namespace scriptable {
|
||||
|
||||
using ScriptableMeshes = QVector<scriptable::ScriptableMeshPointer>;
|
||||
|
||||
/**jsdoc
|
||||
* @typedef {object} Graphics.Model
|
||||
* @property {Uuid} objectID - UUID of corresponding inworld object (if model is associated)
|
||||
* @property {number} numMeshes - The number of submeshes contained in the model.
|
||||
* @property {Graphics.Mesh[]} meshes - Array of submesh references.
|
||||
*/
|
||||
|
||||
class ScriptableModel : public ScriptableModelBase {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUuid objectID MEMBER objectID CONSTANT)
|
||||
|
@ -42,8 +50,6 @@ namespace scriptable {
|
|||
scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap());
|
||||
QString toString() const;
|
||||
|
||||
// QScriptEngine-specific wrappers
|
||||
//glm::uint32 forEachMeshVertexAttribute(QScriptValue callback);
|
||||
protected:
|
||||
glm::uint32 getNumMeshes() { return meshes.size(); }
|
||||
|
||||
|
@ -51,10 +57,7 @@ namespace scriptable {
|
|||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(scriptable::MeshPointer)
|
||||
Q_DECLARE_METATYPE(scriptable::WeakMeshPointer)
|
||||
Q_DECLARE_METATYPE(scriptable::ScriptableModelPointer)
|
||||
Q_DECLARE_METATYPE(scriptable::ScriptableModelBase)
|
||||
Q_DECLARE_METATYPE(scriptable::ScriptableModelBasePointer)
|
||||
Q_DECLARE_METATYPE(QVector<scriptable::ScriptableModelPointer>)
|
||||
Q_DECLARE_METATYPE(scriptable::ScriptableMaterial)
|
||||
Q_DECLARE_METATYPE(scriptable::MultiMaterialMap)
|
||||
|
|
|
@ -21,8 +21,7 @@ namespace graphics {
|
|||
};
|
||||
}
|
||||
namespace gpu {
|
||||
|
||||
DebugEnums<Type> TYPES{
|
||||
DebugEnums<Type> TYPES{
|
||||
{ Type::FLOAT, "float" },
|
||||
{ Type::INT32, "int32" },
|
||||
{ Type::UINT32, "uint32" },
|
||||
|
|
|
@ -604,15 +604,20 @@ bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointe
|
|||
render::Transaction transaction;
|
||||
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
|
||||
meshIndex = meshIndex >= 0 ? meshIndex : 0;
|
||||
partIndex = partIndex >= 0 ? partIndex : 0;
|
||||
meshIndex = max(meshIndex, 0);
|
||||
partIndex = max(partIndex, 0);
|
||||
|
||||
if (meshIndex >= meshes.size()) {
|
||||
if (meshIndex >= (int)meshes.size()) {
|
||||
qDebug() << meshIndex << "meshIndex >= newModel.meshes.size()" << meshes.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mesh = meshes[meshIndex].getMeshPointer();
|
||||
|
||||
if (partIndex >= (int)mesh->getNumParts()) {
|
||||
qDebug() << partIndex << "partIndex >= mesh->getNumParts()" << mesh->getNumParts();
|
||||
return false;
|
||||
}
|
||||
{
|
||||
// update visual geometry
|
||||
render::Transaction transaction;
|
||||
|
|
Loading…
Reference in a new issue