mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 15:54:31 +02:00
Merge pull request #10015 from sethalves/model-scripting-2
model/mesh scripting
This commit is contained in:
commit
49b3fc8674
20 changed files with 430 additions and 100 deletions
|
@ -404,6 +404,9 @@ bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float r
|
|||
float smallestDimensionSize = voxelSize.x;
|
||||
smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.y);
|
||||
smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.z);
|
||||
if (smallestDimensionSize <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::vec3 maxRadiusInVoxelCoords = glm::vec3(radiusWorldCoords / smallestDimensionSize);
|
||||
glm::vec3 centerInVoxelCoords = wtvMatrix * glm::vec4(centerWorldCoords, 1.0f);
|
||||
|
@ -414,21 +417,33 @@ bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float r
|
|||
glm::ivec3 lowI = glm::clamp(low, glm::vec3(0.0f), _voxelVolumeSize);
|
||||
glm::ivec3 highI = glm::clamp(high, glm::vec3(0.0f), _voxelVolumeSize);
|
||||
|
||||
glm::vec3 radials(radiusWorldCoords / voxelSize.x,
|
||||
radiusWorldCoords / voxelSize.y,
|
||||
radiusWorldCoords / voxelSize.z);
|
||||
|
||||
// This three-level for loop iterates over every voxel in the volume that might be in the sphere
|
||||
withWriteLock([&] {
|
||||
for (int z = lowI.z; z < highI.z; z++) {
|
||||
for (int y = lowI.y; y < highI.y; y++) {
|
||||
for (int x = lowI.x; x < highI.x; x++) {
|
||||
// Store our current position as a vector...
|
||||
glm::vec4 pos(x + 0.5f, y + 0.5f, z + 0.5f, 1.0); // consider voxels cenetered on their coordinates
|
||||
// convert to world coordinates
|
||||
glm::vec3 worldPos = glm::vec3(vtwMatrix * pos);
|
||||
// compute how far the current position is from the center of the volume
|
||||
float fDistToCenter = glm::distance(worldPos, centerWorldCoords);
|
||||
// If the current voxel is less than 'radius' units from the center then we set its value
|
||||
if (fDistToCenter <= radiusWorldCoords) {
|
||||
|
||||
// set voxels whose bounding-box touches the sphere
|
||||
AABox voxelBox(glm::vec3(x - 0.5f, y - 0.5f, z - 0.5f), glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
if (voxelBox.touchesAAEllipsoid(centerInVoxelCoords, radials)) {
|
||||
result |= setVoxelInternal(x, y, z, toValue);
|
||||
}
|
||||
|
||||
// TODO -- this version only sets voxels which have centers inside the sphere. which is best?
|
||||
// // Store our current position as a vector...
|
||||
// glm::vec4 pos(x + 0.5f, y + 0.5f, z + 0.5f, 1.0); // consider voxels cenetered on their coordinates
|
||||
// // convert to world coordinates
|
||||
// glm::vec3 worldPos = glm::vec3(vtwMatrix * pos);
|
||||
// // compute how far the current position is from the center of the volume
|
||||
// float fDistToCenter = glm::distance(worldPos, centerWorldCoords);
|
||||
// // If the current voxel is less than 'radius' units from the center then we set its value
|
||||
// if (fDistToCenter <= radiusWorldCoords) {
|
||||
// result |= setVoxelInternal(x, y, z, toValue);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -677,6 +692,8 @@ bool RenderablePolyVoxEntityItem::updateDependents() {
|
|||
_voxelDataDirty = false;
|
||||
} else if (_volDataDirty) {
|
||||
_volDataDirty = false;
|
||||
} else {
|
||||
_meshReady = true;
|
||||
}
|
||||
});
|
||||
if (voxelDataDirty) {
|
||||
|
@ -694,7 +711,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
|||
assert(getType() == EntityTypes::PolyVox);
|
||||
Q_ASSERT(args->_batch);
|
||||
|
||||
updateDependents();
|
||||
if (_voxelDataDirty || _volDataDirty) {
|
||||
updateDependents();
|
||||
}
|
||||
|
||||
model::MeshPointer mesh;
|
||||
glm::vec3 voxelVolumeSize;
|
||||
|
@ -756,6 +775,12 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
|||
0,
|
||||
sizeof(PolyVox::PositionMaterialNormal));
|
||||
|
||||
// TODO -- should we be setting this?
|
||||
// batch.setInputBuffer(gpu::Stream::NORMAL, mesh->getVertexBuffer()._buffer,
|
||||
// 12,
|
||||
// sizeof(PolyVox::PositionMaterialNormal));
|
||||
|
||||
|
||||
batch.setIndexBuffer(gpu::UINT32, mesh->getIndexBuffer()._buffer, 0);
|
||||
|
||||
if (!_xTextureURL.isEmpty() && !_xTexture) {
|
||||
|
@ -1274,23 +1299,27 @@ void RenderablePolyVoxEntityItem::recomputeMesh() {
|
|||
auto indexBuffer = std::make_shared<gpu::Buffer>(vecIndices.size() * sizeof(uint32_t),
|
||||
(gpu::Byte*)vecIndices.data());
|
||||
auto indexBufferPtr = gpu::BufferPointer(indexBuffer);
|
||||
gpu::BufferView indexBufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW));
|
||||
gpu::BufferView indexBufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::INDEX));
|
||||
mesh->setIndexBuffer(indexBufferView);
|
||||
|
||||
const std::vector<PolyVox::PositionMaterialNormal>& vecVertices = polyVoxMesh.getVertices();
|
||||
const std::vector<PolyVox::PositionMaterialNormal>& vecVertices = polyVoxMesh.getRawVertexData();
|
||||
auto vertexBuffer = std::make_shared<gpu::Buffer>(vecVertices.size() * sizeof(PolyVox::PositionMaterialNormal),
|
||||
(gpu::Byte*)vecVertices.data());
|
||||
auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer);
|
||||
gpu::BufferView vertexBufferView(vertexBufferPtr, 0,
|
||||
vertexBufferPtr->getSize(),
|
||||
sizeof(PolyVox::PositionMaterialNormal),
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW));
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
mesh->setVertexBuffer(vertexBufferView);
|
||||
|
||||
|
||||
// TODO -- use 3-byte normals rather than 3-float normals
|
||||
mesh->addAttribute(gpu::Stream::NORMAL,
|
||||
gpu::BufferView(vertexBufferPtr, sizeof(float) * 3,
|
||||
vertexBufferPtr->getSize() ,
|
||||
gpu::BufferView(vertexBufferPtr,
|
||||
sizeof(float) * 3, // polyvox mesh is packed: position, normal, material
|
||||
vertexBufferPtr->getSize(),
|
||||
sizeof(PolyVox::PositionMaterialNormal),
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)));
|
||||
|
||||
std::vector<model::Mesh::Part> parts;
|
||||
parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex
|
||||
|
@ -1312,7 +1341,7 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) {
|
|||
}
|
||||
_mesh = mesh;
|
||||
_meshDirty = true;
|
||||
_meshInitialized = true;
|
||||
_meshReady = true;
|
||||
neighborsNeedUpdate = _neighborsNeedUpdate;
|
||||
_neighborsNeedUpdate = false;
|
||||
});
|
||||
|
@ -1324,7 +1353,7 @@ void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) {
|
|||
void RenderablePolyVoxEntityItem::computeShapeInfoWorker() {
|
||||
// this creates a collision-shape for the physics engine. The shape comes from
|
||||
// _volData for cubic extractors and from _mesh for marching-cube extractors
|
||||
if (!_meshInitialized) {
|
||||
if (!_meshReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1592,7 +1621,7 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) {
|
|||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
||||
bool RenderablePolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) {
|
||||
bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) {
|
||||
if (!updateDependents()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1601,15 +1630,22 @@ bool RenderablePolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QS
|
|||
MeshProxy* meshProxy = nullptr;
|
||||
glm::mat4 transform = voxelToLocalMatrix();
|
||||
withReadLock([&] {
|
||||
if (_meshInitialized) {
|
||||
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)_mesh->getNumVertices();
|
||||
if (!_meshReady) {
|
||||
// we aren't ready to return a mesh. the caller will have to try again later.
|
||||
success = false;
|
||||
} else if (numVertices == 0) {
|
||||
// we are ready, but there are no triangles in the mesh.
|
||||
success = true;
|
||||
} else {
|
||||
success = true;
|
||||
// the mesh will be in voxel-space. transform it into object-space
|
||||
meshProxy = new MeshProxy(
|
||||
_mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
||||
[=](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); },
|
||||
[](uint32_t index){ return index; }));
|
||||
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
|
||||
[&](uint32_t index){ return index; }));
|
||||
result << meshProxy;
|
||||
}
|
||||
});
|
||||
result = meshToScriptValue(engine, meshProxy);
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
void render(RenderArgs* args) override;
|
||||
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
void** intersectedObject, bool precisionPicking) const override;
|
||||
|
||||
|
@ -135,18 +135,19 @@ public:
|
|||
QByteArray volDataToArray(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize) const;
|
||||
|
||||
void setMesh(model::MeshPointer mesh);
|
||||
bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) override;
|
||||
void setCollisionPoints(ShapeInfo::PointCollection points, AABox box);
|
||||
PolyVox::SimpleVolume<uint8_t>* getVolData() { return _volData; }
|
||||
|
||||
uint8_t getVoxelInternal(int x, int y, int z) const;
|
||||
bool setVoxelInternal(int x, int y, int z, uint8_t toValue);
|
||||
|
||||
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; }); }
|
||||
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); }
|
||||
|
||||
// Transparent polyvox didn't seem to be working so disable for now
|
||||
bool isTransparent() override { return false; }
|
||||
|
||||
bool getMeshes(MeshProxyList& result) override;
|
||||
|
||||
protected:
|
||||
virtual void locationChanged(bool tellPhysics = true) override;
|
||||
|
||||
|
@ -157,7 +158,7 @@ private:
|
|||
model::MeshPointer _mesh;
|
||||
gpu::Stream::FormatPointer _vertexFormat;
|
||||
bool _meshDirty { true }; // does collision-shape need to be recomputed?
|
||||
bool _meshInitialized { false };
|
||||
bool _meshReady { false };
|
||||
|
||||
NetworkTexturePointer _xTexture;
|
||||
NetworkTexturePointer _yTexture;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME entities)
|
||||
setup_hifi_library(Network Script)
|
||||
link_hifi_libraries(avatars shared audio octree model fbx networking animation)
|
||||
link_hifi_libraries(avatars shared audio octree model model-networking fbx networking animation)
|
||||
|
||||
target_bullet()
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@ namespace render {
|
|||
#define debugTimeOnly(T) qPrintable(QString("%1").arg(T, 16, 10))
|
||||
#define debugTreeVector(V) V << "[" << V << " in meters ]"
|
||||
|
||||
class MeshProxyList;
|
||||
|
||||
|
||||
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
|
||||
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
|
||||
|
@ -470,9 +472,11 @@ public:
|
|||
|
||||
QUuid getLastEditedBy() const { return _lastEditedBy; }
|
||||
void setLastEditedBy(QUuid value) { _lastEditedBy = value; }
|
||||
|
||||
|
||||
bool matchesJSONFilters(const QJsonObject& jsonFilters) const;
|
||||
|
||||
virtual bool getMeshes(MeshProxyList& result) { return true; }
|
||||
|
||||
protected:
|
||||
|
||||
void setSimulated(bool simulated) { _simulated = simulated; }
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <VariantMapToScriptValue.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <SpatialParentFinder.h>
|
||||
#include <model-networking/MeshProxy.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityActionFactoryInterface.h"
|
||||
|
@ -1031,25 +1032,6 @@ bool EntityScriptingInterface::setVoxelsInCuboid(QUuid entityID, const glm::vec3
|
|||
});
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::voxelsToMesh(QUuid entityID, QScriptValue callback) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
bool success { false };
|
||||
QScriptValue mesh { false };
|
||||
|
||||
polyVoxWorker(entityID, [&](PolyVoxEntityItem& polyVoxEntity) mutable {
|
||||
if (polyVoxEntity.getOnCount() == 0) {
|
||||
success = true;
|
||||
} else {
|
||||
success = polyVoxEntity.getMeshAsScriptValue(callback.engine(), mesh);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
QScriptValueList args { mesh, success };
|
||||
callback.call(QScriptValue(), args);
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector<glm::vec3>& points) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
|
@ -1666,6 +1648,30 @@ bool EntityScriptingInterface::AABoxIntersectsCapsule(const glm::vec3& low, cons
|
|||
return aaBox.findCapsulePenetration(start, end, radius, penetration);
|
||||
}
|
||||
|
||||
void EntityScriptingInterface::getMeshes(QUuid entityID, QScriptValue callback) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::getMeshes no entity with ID" << entityID;
|
||||
QScriptValueList args { callback.engine()->undefinedValue(), false };
|
||||
callback.call(QScriptValue(), args);
|
||||
return;
|
||||
}
|
||||
|
||||
MeshProxyList result;
|
||||
bool success = entity->getMeshes(result);
|
||||
|
||||
if (success) {
|
||||
QScriptValue resultAsScriptValue = meshesToScriptValue(callback.engine(), result);
|
||||
QScriptValueList args { resultAsScriptValue, true };
|
||||
callback.call(QScriptValue(), args);
|
||||
} else {
|
||||
QScriptValueList args { callback.engine()->undefinedValue(), false };
|
||||
callback.call(QScriptValue(), args);
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 EntityScriptingInterface::getEntityTransform(const QUuid& entityID) {
|
||||
glm::mat4 result;
|
||||
if (_entityTree) {
|
||||
|
@ -1682,3 +1688,20 @@ glm::mat4 EntityScriptingInterface::getEntityTransform(const QUuid& entityID) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::mat4 EntityScriptingInterface::getEntityLocalTransform(const QUuid& entityID) {
|
||||
glm::mat4 result;
|
||||
if (_entityTree) {
|
||||
_entityTree->withReadLock([&] {
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID));
|
||||
if (entity) {
|
||||
glm::mat4 translation = glm::translate(entity->getLocalPosition());
|
||||
glm::mat4 rotation = glm::mat4_cast(entity->getLocalOrientation());
|
||||
glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT -
|
||||
entity->getRegistrationPoint());
|
||||
result = translation * rotation * registration;
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -265,7 +265,6 @@ public slots:
|
|||
Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value);
|
||||
Q_INVOKABLE bool setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition,
|
||||
const glm::vec3& cuboidSize, int value);
|
||||
Q_INVOKABLE void voxelsToMesh(QUuid entityID, QScriptValue callback);
|
||||
|
||||
Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector<glm::vec3>& points);
|
||||
Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point);
|
||||
|
@ -330,6 +329,8 @@ public slots:
|
|||
const glm::vec3& start, const glm::vec3& end, float radius);
|
||||
|
||||
|
||||
Q_INVOKABLE void getMeshes(QUuid entityID, QScriptValue callback);
|
||||
|
||||
/**jsdoc
|
||||
* Returns object to world transform, excluding scale
|
||||
*
|
||||
|
@ -339,6 +340,16 @@ public slots:
|
|||
*/
|
||||
Q_INVOKABLE glm::mat4 getEntityTransform(const QUuid& entityID);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Returns object to world transform, excluding scale
|
||||
*
|
||||
* @function Entities.getEntityLocalTransform
|
||||
* @param {EntityID} entityID The ID of the entity whose local transform is to be returned
|
||||
* @return {Mat4} Entity's object to parent transform, excluding scale
|
||||
*/
|
||||
Q_INVOKABLE glm::mat4 getEntityLocalTransform(const QUuid& entityID);
|
||||
|
||||
signals:
|
||||
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||
|
||||
|
|
|
@ -242,7 +242,3 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const {
|
|||
});
|
||||
return voxelDataCopy;
|
||||
}
|
||||
|
||||
bool PolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -135,8 +135,6 @@ class PolyVoxEntityItem : public EntityItem {
|
|||
void setVoxelDataDirty(bool value) { withWriteLock([&] { _voxelDataDirty = value; }); }
|
||||
virtual void recomputeMesh() {};
|
||||
|
||||
virtual bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result);
|
||||
|
||||
protected:
|
||||
glm::vec3 _voxelVolumeSize; // this is always 3 bytes
|
||||
|
||||
|
|
|
@ -40,12 +40,16 @@ static QString formatFloat(double n) {
|
|||
}
|
||||
|
||||
bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
||||
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
|
||||
|
||||
// each mesh's vertices are numbered from zero. We're combining all their vertices into one list here,
|
||||
// so keep track of the start index for each mesh.
|
||||
QList<int> meshVertexStartOffset;
|
||||
QList<int> meshNormalStartOffset;
|
||||
int currentVertexStartOffset = 0;
|
||||
int currentNormalStartOffset = 0;
|
||||
|
||||
// write out all vertices
|
||||
// write out vertices
|
||||
foreach (const MeshPointer& mesh, meshes) {
|
||||
meshVertexStartOffset.append(currentVertexStartOffset);
|
||||
const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer();
|
||||
|
@ -64,10 +68,28 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
|||
}
|
||||
out << "\n";
|
||||
|
||||
// write out normals
|
||||
bool haveNormals = true;
|
||||
foreach (const MeshPointer& mesh, meshes) {
|
||||
meshNormalStartOffset.append(currentNormalStartOffset);
|
||||
const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal);
|
||||
gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements();
|
||||
for (gpu::BufferView::Index i = 0; i < numNormals; i++) {
|
||||
glm::vec3 normal = normalsBufferView.get<glm::vec3>(i);
|
||||
out << "vn ";
|
||||
out << formatFloat(normal[0]) << " ";
|
||||
out << formatFloat(normal[1]) << " ";
|
||||
out << formatFloat(normal[2]) << "\n";
|
||||
}
|
||||
currentNormalStartOffset += numNormals;
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
// write out faces
|
||||
int nth = 0;
|
||||
foreach (const MeshPointer& mesh, meshes) {
|
||||
currentVertexStartOffset = meshVertexStartOffset.takeFirst();
|
||||
currentNormalStartOffset = meshNormalStartOffset.takeFirst();
|
||||
|
||||
const gpu::BufferView& partBuffer = mesh->getPartBuffer();
|
||||
const gpu::BufferView& indexBuffer = mesh->getIndexBuffer();
|
||||
|
@ -104,9 +126,15 @@ bool writeOBJToTextStream(QTextStream& out, QList<MeshPointer> meshes) {
|
|||
indexCount++;
|
||||
|
||||
out << "f ";
|
||||
out << currentVertexStartOffset + index0 + 1 << " ";
|
||||
out << currentVertexStartOffset + index1 + 1 << " ";
|
||||
out << currentVertexStartOffset + index2 + 1 << "\n";
|
||||
if (haveNormals) {
|
||||
out << currentVertexStartOffset + index0 + 1 << "//" << currentVertexStartOffset + index0 + 1 << " ";
|
||||
out << currentVertexStartOffset + index1 + 1 << "//" << currentVertexStartOffset + index1 + 1 << " ";
|
||||
out << currentVertexStartOffset + index2 + 1 << "//" << currentVertexStartOffset + index2 + 1 << "\n";
|
||||
} else {
|
||||
out << currentVertexStartOffset + index0 + 1 << " ";
|
||||
out << currentVertexStartOffset + index1 + 1 << " ";
|
||||
out << currentVertexStartOffset + index2 + 1 << "\n";
|
||||
}
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
|
44
libraries/model-networking/src/model-networking/MeshFace.cpp
Normal file
44
libraries/model-networking/src/model-networking/MeshFace.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// MeshFace.cpp
|
||||
// libraries/model/src/model/
|
||||
//
|
||||
// Created by Seth Alves on 2017-3-23
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "MeshFace.h"
|
||||
|
||||
|
||||
QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("vertices", qVectorIntToScriptValue(engine, meshFace.vertexIndices));
|
||||
return obj;
|
||||
}
|
||||
|
||||
void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult) {
|
||||
qVectorIntFromScriptValue(object.property("vertices"), meshFaceResult.vertexIndices);
|
||||
}
|
||||
|
||||
QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector<MeshFace>& vector) {
|
||||
QScriptValue array = engine->newArray();
|
||||
for (int i = 0; i < vector.size(); i++) {
|
||||
array.setProperty(i, meshFaceToScriptValue(engine, vector.at(i)));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>& result) {
|
||||
int length = array.property("length").toInteger();
|
||||
result.clear();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MeshFace meshFace = MeshFace();
|
||||
meshFaceFromScriptValue(array.property(i), meshFace);
|
||||
result << meshFace;
|
||||
}
|
||||
}
|
43
libraries/model-networking/src/model-networking/MeshFace.h
Normal file
43
libraries/model-networking/src/model-networking/MeshFace.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// MeshFace.h
|
||||
// libraries/model/src/model/
|
||||
//
|
||||
// Created by Seth Alves on 2017-3-23
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_MeshFace_h
|
||||
#define hifi_MeshFace_h
|
||||
|
||||
#include <QScriptEngine>
|
||||
#include <QScriptValueIterator>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
#include <model/Geometry.h>
|
||||
|
||||
using MeshPointer = std::shared_ptr<model::Mesh>;
|
||||
|
||||
class MeshFace {
|
||||
|
||||
public:
|
||||
MeshFace() {}
|
||||
~MeshFace() {}
|
||||
|
||||
QVector<uint32_t> vertexIndices;
|
||||
// TODO -- material...
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(MeshFace)
|
||||
Q_DECLARE_METATYPE(QVector<MeshFace>)
|
||||
|
||||
QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace);
|
||||
void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult);
|
||||
QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector<MeshFace>& vector);
|
||||
void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>& result);
|
||||
|
||||
|
||||
|
||||
#endif // hifi_MeshFace_h
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// MeshProxy.cpp
|
||||
// libraries/model/src/model/
|
||||
//
|
||||
// Created by Seth Alves on 2017-3-22.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "MeshProxy.h"
|
||||
|
||||
|
||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
|
||||
return engine->newQObject(in, QScriptEngine::QtOwnership,
|
||||
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
||||
}
|
||||
|
||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) {
|
||||
out = qobject_cast<MeshProxy*>(value.toQObject());
|
||||
}
|
||||
|
||||
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in) {
|
||||
// QScriptValueList result;
|
||||
QScriptValue result = engine->newArray();
|
||||
int i = 0;
|
||||
foreach (MeshProxy* const meshProxy, in) {
|
||||
result.setProperty(i++, meshToScriptValue(engine, meshProxy));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) {
|
||||
QScriptValueIterator itr(value);
|
||||
|
||||
qDebug() << "in meshesFromScriptValue, value.length =" << value.property("length").toInt32();
|
||||
|
||||
while(itr.hasNext()) {
|
||||
itr.next();
|
||||
MeshProxy* meshProxy = qscriptvalue_cast<MeshProxyList::value_type>(itr.value());
|
||||
if (meshProxy) {
|
||||
out.append(meshProxy);
|
||||
} else {
|
||||
qDebug() << "null meshProxy";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// MeshProxy.h
|
||||
// libraries/script-engine/src
|
||||
// libraries/model/src/model/
|
||||
//
|
||||
// Created by Seth Alves on 2017-1-27.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
|
@ -12,6 +12,10 @@
|
|||
#ifndef hifi_MeshProxy_h
|
||||
#define hifi_MeshProxy_h
|
||||
|
||||
#include <QScriptEngine>
|
||||
#include <QScriptValueIterator>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
#include <model/Geometry.h>
|
||||
|
||||
using MeshPointer = std::shared_ptr<model::Mesh>;
|
||||
|
@ -38,4 +42,11 @@ Q_DECLARE_METATYPE(MeshProxy*);
|
|||
class MeshProxyList : public QList<MeshProxy*> {}; // typedef and using fight with the Qt macros/templates, do this instead
|
||||
Q_DECLARE_METATYPE(MeshProxyList);
|
||||
|
||||
|
||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in);
|
||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out);
|
||||
|
||||
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in);
|
||||
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out);
|
||||
|
||||
#endif // hifi_MeshProxy_h
|
|
@ -145,7 +145,7 @@ model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
|
|||
unsigned char* resultVertexData = new unsigned char[vertexSize];
|
||||
unsigned char* vertexDataCursor = resultVertexData;
|
||||
|
||||
for (gpu::BufferView::Index i = 0; i < numVertices; i ++) {
|
||||
for (gpu::BufferView::Index i = 0; i < numVertices; i++) {
|
||||
glm::vec3 pos = vertexFunc(vertexBufferView.get<glm::vec3>(i));
|
||||
memcpy(vertexDataCursor, &pos, sizeof(pos));
|
||||
vertexDataCursor += sizeof(pos);
|
||||
|
@ -159,7 +159,7 @@ model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
|
|||
unsigned char* resultNormalData = new unsigned char[normalSize];
|
||||
unsigned char* normalDataCursor = resultNormalData;
|
||||
|
||||
for (gpu::BufferView::Index i = 0; i < numNormals; i ++) {
|
||||
for (gpu::BufferView::Index i = 0; i < numNormals; i++) {
|
||||
glm::vec3 normal = normalFunc(normalsBufferView.get<glm::vec3>(i));
|
||||
memcpy(normalDataCursor, &normal, sizeof(normal));
|
||||
normalDataCursor += sizeof(normal);
|
||||
|
@ -173,7 +173,7 @@ model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
|
|||
unsigned char* resultIndexData = new unsigned char[indexSize];
|
||||
unsigned char* indexDataCursor = resultIndexData;
|
||||
|
||||
for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) {
|
||||
for (gpu::BufferView::Index i = 0; i < numIndexes; i++) {
|
||||
uint32_t index = indexFunc(indexBufferView.get<uint32_t>(i));
|
||||
memcpy(indexDataCursor, &index, sizeof(index));
|
||||
indexDataCursor += sizeof(index);
|
||||
|
@ -217,19 +217,18 @@ model::MeshPointer Mesh::map(std::function<glm::vec3(glm::vec3)> vertexFunc,
|
|||
void Mesh::forEach(std::function<void(glm::vec3)> vertexFunc,
|
||||
std::function<void(glm::vec3)> normalFunc,
|
||||
std::function<void(uint32_t)> indexFunc) {
|
||||
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
|
||||
|
||||
// vertex data
|
||||
const gpu::BufferView& vertexBufferView = getVertexBuffer();
|
||||
gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices();
|
||||
for (gpu::BufferView::Index i = 0; i < numVertices; i ++) {
|
||||
for (gpu::BufferView::Index i = 0; i < numVertices; i++) {
|
||||
vertexFunc(vertexBufferView.get<glm::vec3>(i));
|
||||
}
|
||||
|
||||
// normal data
|
||||
int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h
|
||||
const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal);
|
||||
gpu::BufferView::Index numNormals = (gpu::BufferView::Index) normalsBufferView.getNumElements();
|
||||
for (gpu::BufferView::Index i = 0; i < numNormals; i ++) {
|
||||
gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements();
|
||||
for (gpu::BufferView::Index i = 0; i < numNormals; i++) {
|
||||
normalFunc(normalsBufferView.get<glm::vec3>(i));
|
||||
}
|
||||
// TODO -- other attributes
|
||||
|
@ -237,7 +236,7 @@ void Mesh::forEach(std::function<void(glm::vec3)> vertexFunc,
|
|||
// face data
|
||||
const gpu::BufferView& indexBufferView = getIndexBuffer();
|
||||
gpu::BufferView::Index numIndexes = (gpu::BufferView::Index)getNumIndices();
|
||||
for (gpu::BufferView::Index i = 0; i < numIndexes; i ++) {
|
||||
for (gpu::BufferView::Index i = 0; i < numIndexes; i++) {
|
||||
indexFunc(indexBufferView.get<uint32_t>(i));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,36 +12,18 @@
|
|||
#include <QScriptEngine>
|
||||
#include <QScriptValueIterator>
|
||||
#include <QtScript/QScriptValue>
|
||||
#include <model-networking/MeshFace.h>
|
||||
#include "ScriptEngine.h"
|
||||
#include "ScriptEngineLogging.h"
|
||||
#include "ModelScriptingInterface.h"
|
||||
#include "OBJWriter.h"
|
||||
|
||||
ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) {
|
||||
_modelScriptEngine = qobject_cast<ScriptEngine*>(parent);
|
||||
}
|
||||
|
||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
|
||||
return engine->newQObject(in, QScriptEngine::QtOwnership,
|
||||
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
||||
}
|
||||
|
||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) {
|
||||
out = qobject_cast<MeshProxy*>(value.toQObject());
|
||||
}
|
||||
|
||||
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in) {
|
||||
return engine->toScriptValue(in);
|
||||
}
|
||||
|
||||
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) {
|
||||
QScriptValueIterator itr(value);
|
||||
while(itr.hasNext()) {
|
||||
itr.next();
|
||||
MeshProxy* meshProxy = qscriptvalue_cast<MeshProxyList::value_type>(itr.value());
|
||||
if (meshProxy) {
|
||||
out.append(meshProxy);
|
||||
}
|
||||
}
|
||||
qScriptRegisterSequenceMetaType<QList<MeshProxy*>>(_modelScriptEngine);
|
||||
qScriptRegisterMetaType(_modelScriptEngine, meshFaceToScriptValue, meshFaceFromScriptValue);
|
||||
qScriptRegisterMetaType(_modelScriptEngine, qVectorMeshFaceToScriptValue, qVectorMeshFaceFromScriptValue);
|
||||
}
|
||||
|
||||
QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) {
|
||||
|
@ -140,8 +122,6 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) {
|
|||
return meshToScriptValue(_modelScriptEngine, resultProxy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshProxy* meshProxy) {
|
||||
if (!meshProxy) {
|
||||
return QScriptValue(false);
|
||||
|
@ -157,3 +137,57 @@ QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshPro
|
|||
MeshProxy* resultProxy = new MeshProxy(result);
|
||||
return meshToScriptValue(_modelScriptEngine, resultProxy);
|
||||
}
|
||||
|
||||
QScriptValue ModelScriptingInterface::newMesh(const QVector<glm::vec3>& vertices,
|
||||
const QVector<glm::vec3>& normals,
|
||||
const QVector<MeshFace>& faces) {
|
||||
model::MeshPointer mesh(new model::Mesh());
|
||||
|
||||
// vertices
|
||||
auto vertexBuffer = std::make_shared<gpu::Buffer>(vertices.size() * sizeof(glm::vec3), (gpu::Byte*)vertices.data());
|
||||
auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer);
|
||||
gpu::BufferView vertexBufferView(vertexBufferPtr, 0, vertexBufferPtr->getSize(),
|
||||
sizeof(glm::vec3), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
mesh->setVertexBuffer(vertexBufferView);
|
||||
|
||||
if (vertices.size() == normals.size()) {
|
||||
// normals
|
||||
auto normalBuffer = std::make_shared<gpu::Buffer>(normals.size() * sizeof(glm::vec3), (gpu::Byte*)normals.data());
|
||||
auto normalBufferPtr = gpu::BufferPointer(normalBuffer);
|
||||
gpu::BufferView normalBufferView(normalBufferPtr, 0, normalBufferPtr->getSize(),
|
||||
sizeof(glm::vec3), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||
mesh->addAttribute(gpu::Stream::NORMAL, normalBufferView);
|
||||
} else {
|
||||
qCDebug(scriptengine) << "ModelScriptingInterface::newMesh normals must be same length as vertices";
|
||||
}
|
||||
|
||||
// indices (faces)
|
||||
int VERTICES_PER_TRIANGLE = 3;
|
||||
int indexBufferSize = faces.size() * sizeof(uint32_t) * VERTICES_PER_TRIANGLE;
|
||||
unsigned char* indexData = new unsigned char[indexBufferSize];
|
||||
unsigned char* indexDataCursor = indexData;
|
||||
foreach(const MeshFace& meshFace, faces) {
|
||||
for (int i = 0; i < VERTICES_PER_TRIANGLE; i++) {
|
||||
memcpy(indexDataCursor, &meshFace.vertexIndices[i], sizeof(uint32_t));
|
||||
indexDataCursor += sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
auto indexBuffer = std::make_shared<gpu::Buffer>(indexBufferSize, (gpu::Byte*)indexData);
|
||||
auto indexBufferPtr = gpu::BufferPointer(indexBuffer);
|
||||
gpu::BufferView indexBufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW));
|
||||
mesh->setIndexBuffer(indexBufferView);
|
||||
|
||||
// parts
|
||||
std::vector<model::Mesh::Part> parts;
|
||||
parts.emplace_back(model::Mesh::Part((model::Index)0, // startIndex
|
||||
(model::Index)faces.size() * 3, // numIndices
|
||||
(model::Index)0, // baseVertex
|
||||
model::Mesh::TRIANGLES)); // topology
|
||||
mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(model::Mesh::Part),
|
||||
(gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL));
|
||||
|
||||
|
||||
|
||||
MeshProxy* meshProxy = new MeshProxy(mesh);
|
||||
return meshToScriptValue(_modelScriptEngine, meshProxy);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
#include <QScriptValue>
|
||||
#include <OBJWriter.h>
|
||||
#include <model/Geometry.h>
|
||||
#include "MeshProxy.h"
|
||||
#include <model-networking/MeshProxy.h>
|
||||
#include <model-networking/MeshFace.h>
|
||||
|
||||
using MeshPointer = std::shared_ptr<model::Mesh>;
|
||||
class ScriptEngine;
|
||||
|
@ -31,15 +32,12 @@ public:
|
|||
Q_INVOKABLE QString meshToOBJ(MeshProxyList in);
|
||||
Q_INVOKABLE QScriptValue appendMeshes(MeshProxyList in);
|
||||
Q_INVOKABLE QScriptValue transformMesh(glm::mat4 transform, MeshProxy* meshProxy);
|
||||
Q_INVOKABLE QScriptValue newMesh(const QVector<glm::vec3>& vertices,
|
||||
const QVector<glm::vec3>& normals,
|
||||
const QVector<MeshFace>& faces);
|
||||
|
||||
private:
|
||||
ScriptEngine* _modelScriptEngine { nullptr };
|
||||
};
|
||||
|
||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in);
|
||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out);
|
||||
|
||||
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in);
|
||||
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out);
|
||||
|
||||
#endif // hifi_ModelScriptingInterface_h
|
||||
|
|
|
@ -436,6 +436,38 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec4& origin, const glm::vec4&
|
|||
return getClosestPointOnFace(glm::vec3(origin), face);
|
||||
}
|
||||
|
||||
bool AABox::touchesAAEllipsoid(const glm::vec3& center, const glm::vec3& radials) const {
|
||||
// handle case where ellipsoid's alix-aligned box doesn't touch this AABox
|
||||
if (_corner.x - radials.x > center.x ||
|
||||
_corner.y - radials.y > center.y ||
|
||||
_corner.z - radials.z > center.z ||
|
||||
_corner.x + _scale.x + radials.x < center.x ||
|
||||
_corner.y + _scale.y + radials.y < center.y ||
|
||||
_corner.z + _scale.z + radials.z < center.z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// handle case where ellipsoid is entirely inside this AABox
|
||||
if (contains(center)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < FACE_COUNT; i++) {
|
||||
glm::vec3 closest = getClosestPointOnFace(center, (BoxFace)i) - center;
|
||||
float x = closest.x;
|
||||
float y = closest.y;
|
||||
float z = closest.z;
|
||||
float a = radials.x;
|
||||
float b = radials.y;
|
||||
float c = radials.z;
|
||||
if (x*x/(a*a) + y*y/(b*b) + z*z/(c*c) < 1.0f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
glm::vec4 AABox::getPlane(BoxFace face) const {
|
||||
switch (face) {
|
||||
case MIN_X_FACE: return glm::vec4(-1.0f, 0.0f, 0.0f, _corner.x);
|
||||
|
|
|
@ -70,6 +70,7 @@ public:
|
|||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal) const;
|
||||
bool touchesSphere(const glm::vec3& center, float radius) const; // fast but may generate false positives
|
||||
bool touchesAAEllipsoid(const glm::vec3& center, const glm::vec3& radials) const;
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ void registerMetaTypes(QScriptEngine* engine) {
|
|||
qScriptRegisterMetaType(engine, qVectorQuatToScriptValue, qVectorQuatFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, qVectorBoolToScriptValue, qVectorBoolFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, qVectorFloatToScriptValue, qVectorFloatFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, qVectorIntToScriptValue, qVectorIntFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue);
|
||||
qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue);
|
||||
|
@ -386,6 +387,15 @@ QScriptValue qVectorFloatToScriptValue(QScriptEngine* engine, const QVector<floa
|
|||
return array;
|
||||
}
|
||||
|
||||
QScriptValue qVectorIntToScriptValue(QScriptEngine* engine, const QVector<uint32_t>& vector) {
|
||||
QScriptValue array = engine->newArray();
|
||||
for (int i = 0; i < vector.size(); i++) {
|
||||
int num = vector.at(i);
|
||||
array.setProperty(i, QScriptValue(num));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
void qVectorFloatFromScriptValue(const QScriptValue& array, QVector<float>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
|
@ -393,6 +403,15 @@ void qVectorFloatFromScriptValue(const QScriptValue& array, QVector<float>& vect
|
|||
vector << array.property(i).toVariant().toFloat();
|
||||
}
|
||||
}
|
||||
|
||||
void qVectorIntFromScriptValue(const QScriptValue& array, QVector<uint32_t>& vector) {
|
||||
int length = array.property("length").toInteger();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
vector << array.property(i).toVariant().toInt();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
QVector<glm::vec3> qVectorVec3FromScriptValue(const QScriptValue& array){
|
||||
QVector<glm::vec3> newVector;
|
||||
|
|
|
@ -113,6 +113,10 @@ QScriptValue qVectorFloatToScriptValue(QScriptEngine* engine, const QVector<floa
|
|||
void qVectorFloatFromScriptValue(const QScriptValue& array, QVector<float>& vector);
|
||||
QVector<float> qVectorFloatFromScriptValue(const QScriptValue& array);
|
||||
|
||||
// vector<uint32_t>
|
||||
QScriptValue qVectorIntToScriptValue(QScriptEngine* engine, const QVector<uint32_t>& vector);
|
||||
void qVectorIntFromScriptValue(const QScriptValue& array, QVector<uint32_t>& vector);
|
||||
|
||||
QVector<QUuid> qVectorQUuidFromScriptValue(const QScriptValue& array);
|
||||
|
||||
QScriptValue aaCubeToScriptValue(QScriptEngine* engine, const AACube& aaCube);
|
||||
|
|
Loading…
Reference in a new issue