diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index da588bc316..d656464c10 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -70,7 +70,7 @@ void Agent::handleOctreePacket(QSharedPointer packet, SharedNodePointe // pull out the piggybacked packet and create a new QSharedPointer for it int piggyBackedSizeWithHeader = packet->getPayloadSize() - statsMessageLength; - std::unique_ptr buffer = std::unique_ptr(new char[piggyBackedSizeWithHeader]); + auto buffer = std::unique_ptr(new char[piggyBackedSizeWithHeader]); memcpy(buffer.get(), packet->getPayload() + statsMessageLength, piggyBackedSizeWithHeader); auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggyBackedSizeWithHeader, packet->getSenderSockAddr()); @@ -107,6 +107,7 @@ void Agent::handleAudioPacket(QSharedPointer packet) { } const QString AGENT_LOGGING_NAME = "agent"; +const int PING_INTERVAL = 1000; void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); @@ -118,6 +119,10 @@ void Agent::run() { << NodeType::EntityServer ); + _pingTimer = new QTimer(this); + connect(_pingTimer, SIGNAL(timeout()), SLOT(sendPingRequests())); + _pingTimer->start(PING_INTERVAL); + // figure out the URL for the script for this agent assignment QUrl scriptURL; if (_payload.isEmpty()) { @@ -193,7 +198,27 @@ void Agent::run() { void Agent::aboutToFinish() { _scriptEngine.stop(); - + + _pingTimer->stop(); + delete _pingTimer; + // our entity tree is going to go away so tell that to the EntityScriptingInterface DependencyManager::get()->setEntityTree(NULL); } + +void Agent::sendPingRequests() { + auto nodeList = DependencyManager::get(); + + nodeList->eachMatchingNode([](const SharedNodePointer& node)->bool { + switch (node->getType()) { + case NodeType::AvatarMixer: + case NodeType::AudioMixer: + case NodeType::EntityServer: + return true; + default: + return false; + } + }, [nodeList](const SharedNodePointer& node) { + nodeList->sendPacket(nodeList->constructPingPacket(), *node); + }); +} diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 241e14439c..4c207e59aa 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -58,11 +58,13 @@ private slots: void handleAudioPacket(QSharedPointer packet); void handleOctreePacket(QSharedPointer packet, SharedNodePointer senderNode); void handleJurisdictionPacket(QSharedPointer packet, SharedNodePointer senderNode); + void sendPingRequests(); private: ScriptEngine _scriptEngine; EntityEditPacketSender _entityEditSender; EntityTreeHeadlessViewer _entityViewer; + QTimer* _pingTimer; MixedAudioStream _receivedAudioStream; float _lastReceivedAudioLoudness; diff --git a/examples/inspect.js b/examples/inspect.js index 0df90fbac3..555b4105b7 100644 --- a/examples/inspect.js +++ b/examples/inspect.js @@ -23,7 +23,7 @@ var RAD_TO_DEG = 180.0 / PI; var AZIMUTH_RATE = 90.0; var ALTITUDE_RATE = 200.0; var RADIUS_RATE = 1.0 / 100.0; -var PAN_RATE = 50.0; +var PAN_RATE = 250.0; var Y_AXIS = { x: 0, @@ -139,7 +139,7 @@ function handlePanMode(dx, dy) { var right = Quat.getRight(Camera.getOrientation()); var distance = Vec3.length(vector); - var dv = Vec3.sum(Vec3.multiply(up, -distance * dy / PAN_RATE), Vec3.multiply(right, distance * dx / PAN_RATE)); + var dv = Vec3.sum(Vec3.multiply(up, distance * dy / PAN_RATE), Vec3.multiply(right, -distance * dx / PAN_RATE)); center = Vec3.sum(center, dv); position = Vec3.sum(position, dv); diff --git a/ice-server/src/IceServer.cpp b/ice-server/src/IceServer.cpp index 46c1582e7d..2a4e2b4300 100644 --- a/ice-server/src/IceServer.cpp +++ b/ice-server/src/IceServer.cpp @@ -50,7 +50,7 @@ void IceServer::processDatagrams() { while (_serverSocket.hasPendingDatagrams()) { // setup a buffer to read the packet into int packetSizeWithHeader = _serverSocket.pendingDatagramSize(); - std::unique_ptr buffer = std::unique_ptr(new char[packetSizeWithHeader]); + auto buffer = std::unique_ptr(new char[packetSizeWithHeader]); _serverSocket.readDatagram(buffer.get(), packetSizeWithHeader, sendingSockAddr.getAddressPointer(), sendingSockAddr.getPortPointer()); diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index 7bb94323b7..1abbb21089 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -57,7 +57,7 @@ void OctreePacketProcessor::processPacket(QSharedPointer packet, Share if (piggybackBytes) { // construct a new packet from the piggybacked one - std::unique_ptr buffer = std::unique_ptr(new char[piggybackBytes]); + auto buffer = std::unique_ptr(new char[piggybackBytes]); memcpy(buffer.get(), packet->getPayload() + statsMessageLength, piggybackBytes); auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggybackBytes, packet->getSenderSockAddr()); diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 53f1b4ce21..fafb759439 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -119,19 +119,21 @@ void Circle3DOverlay::render(RenderArgs* args) { float angle = startAt; float angleInRadians = glm::radians(angle); - glm::vec2 firstInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); - glm::vec2 firstOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); - - points << firstInnerPoint << firstOuterPoint; + glm::vec2 mostRecentInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); + glm::vec2 mostRecentOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); while (angle < endAt) { angleInRadians = glm::radians(angle); glm::vec2 thisInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); glm::vec2 thisOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); - points << thisOuterPoint << thisInnerPoint; + points << mostRecentInnerPoint << mostRecentOuterPoint << thisOuterPoint; // first triangle + points << mostRecentInnerPoint << thisInnerPoint << thisOuterPoint; // second triangle angle += SLICE_ANGLE; + + mostRecentInnerPoint = thisInnerPoint; + mostRecentOuterPoint = thisOuterPoint; } // get the last slice portion.... @@ -139,13 +141,14 @@ void Circle3DOverlay::render(RenderArgs* args) { angleInRadians = glm::radians(angle); glm::vec2 lastInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); glm::vec2 lastOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); - - points << lastOuterPoint << lastInnerPoint; + + points << mostRecentInnerPoint << mostRecentOuterPoint << lastOuterPoint; // first triangle + points << mostRecentInnerPoint << lastInnerPoint << lastOuterPoint; // second triangle geometryCache->updateVertices(_quadVerticesID, points, color); } - geometryCache->renderVertices(batch, gpu::QUAD_STRIP, _quadVerticesID); + geometryCache->renderVertices(batch, gpu::TRIANGLES, _quadVerticesID); } else { if (_lineVerticesID == GeometryCache::UNKNOWN_ID) { diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 908310d504..a3d3a72043 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1037,9 +1037,14 @@ bool AudioClient::outputLocalInjector(bool isStereo, AudioInjector* injector) { localOutput->moveToThread(injector->getLocalBuffer()->thread()); // have it be stopped when that local buffer is about to close - connect(localOutput, &QAudioOutput::stateChanged, this, &AudioClient::audioStateChanged); - connect(this, &AudioClient::audioFinished, localOutput, &QAudioOutput::stop); - connect(this, &AudioClient::audioFinished, injector, &AudioInjector::stop); + // We don't want to stop this localOutput and injector whenever this AudioClient singleton goes idle, + // only when the localOutput does. But the connection is to localOutput, so that it happens on the right thread. + connect(localOutput, &QAudioOutput::stateChanged, localOutput, [=](QAudio::State state) { + if (state == QAudio::IdleState) { + localOutput->stop(); + injector->stop(); + } + }); connect(injector->getLocalBuffer(), &QIODevice::aboutToClose, localOutput, &QAudioOutput::stop); @@ -1358,9 +1363,3 @@ void AudioClient::saveSettings() { windowSecondsForDesiredReduction.set(_receivedAudioStream.getWindowSecondsForDesiredReduction()); repetitionWithFade.set(_receivedAudioStream.getRepetitionWithFade()); } - -void AudioClient::audioStateChanged(QAudio::State state) { - if (state == QAudio::IdleState) { - emit audioFinished(); - } -} diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index a1d08ec540..3205aeda1d 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -209,9 +209,6 @@ protected: deleteLater(); } -private slots: - void audioStateChanged(QAudio::State state); - private: void outputFormatChanged(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 61253ba6ba..ebe4ac6014 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -114,7 +114,8 @@ _glowLevelChanged(false), _localRenderAlphaChanged(false), _defaultSettings(true), -_naturalDimensions(1.0f, 1.0f, 1.0f) +_naturalDimensions(1.0f, 1.0f, 1.0f), +_naturalPosition(0.0f, 0.0f, 0.0f) { } @@ -128,6 +129,11 @@ void EntityItemProperties::setSittingPoints(const QVector& sitting } } +void EntityItemProperties::calculateNaturalPosition(const glm::vec3& min, const glm::vec3& max) { + glm::vec3 halfDimension = (max - min) / 2.0f; + _naturalPosition = max - halfDimension; +} + bool EntityItemProperties::animationSettingsChanged() const { return _animationSettingsChanged; } @@ -378,6 +384,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(dimensions); if (!skipDefaults) { COPY_PROPERTY_TO_QSCRIPTVALUE(naturalDimensions); // gettable, but not settable + COPY_PROPERTY_TO_QSCRIPTVALUE(naturalPosition); } COPY_PROPERTY_TO_QSCRIPTVALUE(rotation); COPY_PROPERTY_TO_QSCRIPTVALUE(velocity); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 4532ffd67b..3ce6040d19 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -192,7 +192,10 @@ public: const glm::vec3& getNaturalDimensions() const { return _naturalDimensions; } void setNaturalDimensions(const glm::vec3& value) { _naturalDimensions = value; } - + + const glm::vec3& getNaturalPosition() const { return _naturalPosition; } + void calculateNaturalPosition(const glm::vec3& min, const glm::vec3& max); + const QStringList& getTextureNames() const { return _textureNames; } void setTextureNames(const QStringList& value) { _textureNames = value; } @@ -232,6 +235,7 @@ private: QVector _sittingPoints; QStringList _textureNames; glm::vec3 _naturalDimensions; + glm::vec3 _naturalPosition; }; Q_DECLARE_METATYPE(EntityItemProperties); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 36fcc17a71..12f5ffe190 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -118,6 +118,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit results.setSittingPoints(geometry->sittingPoints); Extents meshExtents = geometry->getUnscaledMeshExtents(); results.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); + results.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); } } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 83cbe30b30..3b7d18f1d8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -829,6 +829,56 @@ public: std::vector attributes; }; +gpu::BufferPointer FBXMeshPart::getTrianglesForQuads() const { + // if we've been asked for our triangulation of the original quads, but we don't yet have them + // then create them now. + if (!trianglesForQuadsAvailable) { + trianglesForQuadsAvailable = true; + + quadsAsTrianglesIndicesBuffer = std::make_shared(); + + // QVector quadIndices; // original indices from the FBX mesh + QVector quadsAsTrianglesIndices; // triangle versions of quads converted when first needed + const int INDICES_PER_ORIGINAL_QUAD = 4; + const int INDICES_PER_TRIANGULATED_QUAD = 6; + int numberOfQuads = quadIndices.size() / INDICES_PER_ORIGINAL_QUAD; + + quadsAsTrianglesIndices.resize(numberOfQuads * INDICES_PER_TRIANGULATED_QUAD); + + int originalIndex = 0; + int triangulatedIndex = 0; + for (int fromQuad = 0; fromQuad < numberOfQuads; fromQuad++) { + int i0 = quadIndices[originalIndex + 0]; + int i1 = quadIndices[originalIndex + 1]; + int i2 = quadIndices[originalIndex + 2]; + int i3 = quadIndices[originalIndex + 3]; + + // Sam's recommended triangle slices + // Triangle tri1 = { v0, v1, v3 }; + // Triangle tri2 = { v1, v2, v3 }; + // NOTE: Random guy on the internet's recommended triangle slices + // Triangle tri1 = { v0, v1, v2 }; + // Triangle tri2 = { v2, v3, v0 }; + + quadsAsTrianglesIndices[triangulatedIndex + 0] = i0; + quadsAsTrianglesIndices[triangulatedIndex + 1] = i1; + quadsAsTrianglesIndices[triangulatedIndex + 2] = i3; + + quadsAsTrianglesIndices[triangulatedIndex + 3] = i1; + quadsAsTrianglesIndices[triangulatedIndex + 4] = i2; + quadsAsTrianglesIndices[triangulatedIndex + 5] = i3; + + originalIndex += INDICES_PER_ORIGINAL_QUAD; + triangulatedIndex += INDICES_PER_TRIANGULATED_QUAD; + } + + trianglesForQuadsIndicesCount = INDICES_PER_TRIANGULATED_QUAD * numberOfQuads; + quadsAsTrianglesIndicesBuffer->append(quadsAsTrianglesIndices.size() * sizeof(quint32), (gpu::Byte*)quadsAsTrianglesIndices.data()); + + } + return quadsAsTrianglesIndicesBuffer; +} + void appendIndex(MeshData& data, QVector& indices, int index) { if (index >= data.polygonIndices.size()) { return; @@ -1088,7 +1138,6 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { appendIndex(data, part.quadIndices, beginIndex++); appendIndex(data, part.quadIndices, beginIndex++); appendIndex(data, part.quadIndices, beginIndex++); - } else { for (int nextIndex = beginIndex + 1;; ) { appendIndex(data, part.triangleIndices, beginIndex); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index f931bd5e7e..b8a22b0b80 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -105,9 +105,10 @@ public: class FBXMeshPart { public: - QVector quadIndices; - QVector triangleIndices; - + QVector quadIndices; // original indices from the FBX mesh + QVector triangleIndices; // original indices from the FBX mesh + mutable gpu::BufferPointer quadsAsTrianglesIndicesBuffer; + glm::vec3 diffuseColor; glm::vec3 specularColor; glm::vec3 emissiveColor; @@ -122,6 +123,10 @@ public: QString materialID; model::MaterialPointer _material; + mutable bool trianglesForQuadsAvailable = false; + mutable int trianglesForQuadsIndicesCount = 0; + + gpu::BufferPointer getTrianglesForQuads() const; }; /// A single mesh (with optional blendshapes) extracted from an FBX document. diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 981a560965..b710a44f39 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -213,9 +213,6 @@ enum Primitive { TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN, - QUADS, - QUAD_STRIP, - NUM_PRIMITIVES, }; diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index 888fd1164d..7ce54665be 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -23,8 +23,6 @@ static const GLenum _primitiveToGLmode[gpu::NUM_PRIMITIVES] = { GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, - GL_QUADS, - GL_QUAD_STRIP, }; static const GLenum _elementTypeToGLType[gpu::NUM_TYPES] = { diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index 16ebb60b72..5ef414a2d1 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -71,7 +71,7 @@ public: LINE_STRIP, TRIANGLES, TRIANGLE_STRIP, - QUADS, + QUADS, // NOTE: These must be translated to triangles before rendering QUAD_STRIP, NUM_TOPOLOGIES, diff --git a/libraries/networking/src/NLPacket.cpp b/libraries/networking/src/NLPacket.cpp index 7a6503dbc3..7ec10fc4ce 100644 --- a/libraries/networking/src/NLPacket.cpp +++ b/libraries/networking/src/NLPacket.cpp @@ -46,7 +46,7 @@ std::unique_ptr NLPacket::create(PacketType::Value type, qint64 size) return packet; } -std::unique_ptr NLPacket::fromReceivedPacket(std::unique_ptr data, qint64 size, +std::unique_ptr NLPacket::fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) { // Fail with null data Q_ASSERT(data); @@ -85,7 +85,7 @@ NLPacket::NLPacket(const NLPacket& other) : Packet(other) { } -NLPacket::NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +NLPacket::NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : Packet(std::move(data), size, senderSockAddr) { adjustPayloadStartAndCapacity(); diff --git a/libraries/networking/src/NLPacket.h b/libraries/networking/src/NLPacket.h index 669278ed65..6ebf15ffec 100644 --- a/libraries/networking/src/NLPacket.h +++ b/libraries/networking/src/NLPacket.h @@ -20,7 +20,7 @@ class NLPacket : public Packet { Q_OBJECT public: static std::unique_ptr create(PacketType::Value type, qint64 size = -1); - static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, + static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); // Provided for convenience, try to limit use static std::unique_ptr createCopy(const NLPacket& other); @@ -45,7 +45,7 @@ protected: NLPacket(PacketType::Value type); NLPacket(PacketType::Value type, qint64 size); - NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); NLPacket(const NLPacket& other); void readSourceID(); diff --git a/libraries/networking/src/PacketReceiver.cpp b/libraries/networking/src/PacketReceiver.cpp index 5fc327673d..b1a77d4c39 100644 --- a/libraries/networking/src/PacketReceiver.cpp +++ b/libraries/networking/src/PacketReceiver.cpp @@ -243,7 +243,7 @@ void PacketReceiver::processDatagrams() { while (nodeList && nodeList->getNodeSocket().hasPendingDatagrams()) { // setup a buffer to read the packet into int packetSizeWithHeader = nodeList->getNodeSocket().pendingDatagramSize(); - std::unique_ptr buffer = std::unique_ptr(new char[packetSizeWithHeader]); + auto buffer = std::unique_ptr(new char[packetSizeWithHeader]); // if we're supposed to drop this packet then break out here if (_shouldDropPackets) { diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index 02a44c4a4f..13f8a39e26 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -31,7 +31,7 @@ std::unique_ptr Packet::create(PacketType::Value type, qint64 size) { return packet; } -std::unique_ptr Packet::fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) { +std::unique_ptr Packet::fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) { // Fail with invalid size Q_ASSERT(size >= 0); @@ -82,7 +82,7 @@ Packet::Packet(PacketType::Value type, qint64 size) : } } -Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : _packetSize(size), _packet(std::move(data)), _senderSockAddr(senderSockAddr) @@ -110,7 +110,7 @@ Packet& Packet::operator=(const Packet& other) { _type = other._type; _packetSize = other._packetSize; - _packet = std::unique_ptr(new char[_packetSize]); + _packet = std::unique_ptr(new char[_packetSize]); memcpy(_packet.get(), other._packet.get(), _packetSize); _payloadStart = _packet.get() + (other._payloadStart - other._packet.get()); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index b4c53b8165..91b5974e09 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -27,7 +27,7 @@ public: static const qint64 PACKET_WRITE_ERROR; static std::unique_ptr create(PacketType::Value type, qint64 size = -1); - static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); // Provided for convenience, try to limit use static std::unique_ptr createCopy(const Packet& other); @@ -88,7 +88,7 @@ public: protected: Packet(PacketType::Value type, qint64 size); - Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); Packet(const Packet& other); Packet& operator=(const Packet& other); Packet(Packet&& other); @@ -109,7 +109,7 @@ protected: PacketVersion _version; // Packet version qint64 _packetSize = 0; // Total size of the allocated memory - std::unique_ptr _packet; // Allocated memory + std::unique_ptr _packet; // Allocated memory char* _payloadStart = nullptr; // Start of the payload qint64 _payloadCapacity = 0; // Total capacity of the payload diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index feaf9105a6..c793c9dc82 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1012,12 +1012,12 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co } const int FLOATS_PER_VERTEX = 2; // vertices - const int vertices = 4; + const int VERTICES = 4; // 1 quad = 4 vertices if (!details.isCreated) { details.isCreated = true; - details.vertices = vertices; + details.vertices = VERTICES; details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared(); @@ -1037,11 +1037,12 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { + float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { minCorner.x, minCorner.y, maxCorner.x, minCorner.y, + minCorner.x, maxCorner.y, maxCorner.x, maxCorner.y, - minCorner.x, maxCorner.y }; + }; const int NUM_COLOR_SCALARS_PER_QUAD = 4; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | @@ -1050,14 +1051,13 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co ((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); } batch.setInputFormat(details.streamFormat); batch.setInputStream(0, *details.stream); - batch.draw(gpu::QUADS, 4, 0); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } void GeometryCache::renderUnitCube(gpu::Batch& batch) { @@ -1102,23 +1102,25 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co } const int FLOATS_PER_VERTEX = 2 * 2; // text coords & vertices - const int vertices = 4; + const int VERTICES = 4; // 1 quad = 4 vertices const int NUM_POS_COORDS = 2; const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); if (!details.isCreated) { details.isCreated = true; - details.vertices = vertices; + 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; @@ -1130,11 +1132,12 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { + float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { 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, - minCorner.x, maxCorner.y, texCoordMinCorner.x, texCoordMaxCorner.y }; + }; const int NUM_COLOR_SCALARS_PER_QUAD = 4; @@ -1144,14 +1147,13 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co ((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); } batch.setInputFormat(details.streamFormat); batch.setInputStream(0, *details.stream); - batch.draw(gpu::QUADS, 4, 0); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) { @@ -1177,21 +1179,23 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co } const int FLOATS_PER_VERTEX = 3; // vertices - const int vertices = 4; + const int VERTICES = 4; // 1 quad = 4 vertices if (!details.isCreated) { details.isCreated = true; - details.vertices = vertices; + 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; @@ -1202,11 +1206,12 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { + float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { minCorner.x, minCorner.y, minCorner.z, maxCorner.x, minCorner.y, minCorner.z, + minCorner.x, maxCorner.y, maxCorner.z, maxCorner.x, maxCorner.y, maxCorner.z, - minCorner.x, maxCorner.y, maxCorner.z }; + }; const int NUM_COLOR_SCALARS_PER_QUAD = 4; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | @@ -1215,14 +1220,13 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co ((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); } batch.setInputFormat(details.streamFormat); batch.setInputStream(0, *details.stream); - batch.draw(gpu::QUADS, 4, 0); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft, @@ -1267,14 +1271,14 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons } const int FLOATS_PER_VERTEX = 3 + 2; // 3d vertices + text coords - const int vertices = 4; + const int VERTICES = 4; // 1 quad = 4 vertices const int NUM_POS_COORDS = 3; const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); if (!details.isCreated) { details.isCreated = true; - details.vertices = vertices; + 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(); @@ -1295,10 +1299,10 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride); - float vertexBuffer[vertices * FLOATS_PER_VERTEX] = { - topLeft.x, topLeft.y, topLeft.z, texCoordTopLeft.x, texCoordTopLeft.y, + float vertexBuffer[VERTICES * FLOATS_PER_VERTEX] = { 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, }; @@ -1315,7 +1319,7 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons batch.setInputFormat(details.streamFormat); batch.setInputStream(0, *details.stream); - batch.draw(gpu::QUADS, 4, 0); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ab4f780e81..eb2fe63a40 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -240,6 +240,9 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { }; void Model::initJointTransforms() { + if (!_geometry) { + return; + } const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; _rig->initJointTransforms(parentTransform); @@ -421,6 +424,9 @@ bool Model::updateGeometry() { deleteGeometry(); _dilatedTextures.clear(); + if (!geometry) { + std::cout << "WARNING: no geometry in Model::updateGeometry\n"; + } setGeometry(geometry); _meshGroupsKnown = false; @@ -1751,8 +1757,11 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran } if (part.quadIndices.size() > 0) { - batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); + batch.setIndexBuffer(gpu::UINT32, part.getTrianglesForQuads(), 0); + batch.drawIndexed(gpu::TRIANGLES, part.trianglesForQuadsIndicesCount, 0); + offset += part.quadIndices.size() * sizeof(int); + batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); // restore this in case there are triangles too } if (part.triangleIndices.size() > 0) { diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index b341f444e6..3cedcdcbc1 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -18,8 +18,12 @@ struct TextureVertex { TextureVertex(const glm::vec2& pos, const glm::vec2& tex) : pos(pos), tex(tex) {} }; +static const int NUMBER_OF_INDICES_PER_QUAD = 6; // 1 quad = 2 triangles +static const int VERTICES_PER_QUAD = 4; // 1 quad = 4 vertices + struct QuadBuilder { - TextureVertex vertices[4]; + TextureVertex vertices[VERTICES_PER_QUAD]; + QuadBuilder(const glm::vec2& min, const glm::vec2& size, const glm::vec2& texMin, const glm::vec2& texSize) { // min = bottomLeft @@ -249,6 +253,9 @@ void Font::setupGPU() { void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2& bounds) { _verticesBuffer = std::make_shared(); _numVertices = 0; + _indicesBuffer = std::make_shared(); + _numIndices = 0; + _lastStringRendered = str; _lastBounds = bounds; @@ -284,10 +291,28 @@ void Font::rebuildVertices(float x, float y, const QString& str, const glm::vec2 if (!isNewLine) { for (auto c : token) { auto glyph = _glyphs[c]; + quint16 verticesOffset = _numVertices; QuadBuilder qd(glyph, advance - glm::vec2(0.0f, _ascent)); _verticesBuffer->append(sizeof(QuadBuilder), (const gpu::Byte*)&qd); _numVertices += 4; + + // Sam's recommended triangle slices + // Triangle tri1 = { v0, v1, v3 }; + // Triangle tri2 = { v1, v2, v3 }; + // NOTE: Random guy on the internet's recommended triangle slices + // Triangle tri1 = { v0, v1, v2 }; + // Triangle tri2 = { v2, v3, v0 }; + quint16 indices[NUMBER_OF_INDICES_PER_QUAD]; + indices[0] = verticesOffset + 0; + indices[1] = verticesOffset + 1; + indices[2] = verticesOffset + 3; + indices[3] = verticesOffset + 1; + indices[4] = verticesOffset + 2; + indices[5] = verticesOffset + 3; + _indicesBuffer->append(sizeof(indices), (const gpu::Byte*)indices); + _numIndices += NUMBER_OF_INDICES_PER_QUAD; + // Advance by glyph size advance.x += glyph.d; @@ -318,5 +343,6 @@ void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, c batch.setInputFormat(_format); batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); - batch.draw(gpu::QUADS, _numVertices, 0); + batch.setIndexBuffer(gpu::UINT16, _indicesBuffer, 0); + batch.drawIndexed(gpu::TRIANGLES, _numIndices, 0); } diff --git a/libraries/render-utils/src/text/Font.h b/libraries/render-utils/src/text/Font.h index 55801419f9..e10360d45f 100644 --- a/libraries/render-utils/src/text/Font.h +++ b/libraries/render-utils/src/text/Font.h @@ -64,8 +64,10 @@ private: gpu::TexturePointer _texture; gpu::Stream::FormatPointer _format; gpu::BufferPointer _verticesBuffer; + gpu::BufferPointer _indicesBuffer; gpu::BufferStreamPointer _stream; unsigned int _numVertices = 0; + unsigned int _numIndices = 0; int _fontLoc = -1; int _outlineLoc = -1; diff --git a/tools/vhacd-util/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp index 33029d6844..3c02c956e4 100644 --- a/tools/vhacd-util/src/VHACDUtil.cpp +++ b/tools/vhacd-util/src/VHACDUtil.cpp @@ -12,6 +12,8 @@ #include #include "VHACDUtil.h" +const float COLLISION_TETRAHEDRON_SCALE = 0.25f; + // FBXReader jumbles the order of the meshes by reading them back out of a hashtable. This will put // them back in the order in which they appeared in the file. @@ -127,12 +129,14 @@ void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result, continue; } + // from the middle of the triangle, pull a point down to form a tetrahedron. float dropAmount = 0; dropAmount = glm::max(glm::length(p1 - p0), dropAmount); dropAmount = glm::max(glm::length(p2 - p1), dropAmount); dropAmount = glm::max(glm::length(p0 - p2), dropAmount); + dropAmount *= COLLISION_TETRAHEDRON_SCALE; - glm::vec3 p3 = av - glm::vec3(0, dropAmount, 0); // a point 1 meter below the average of this triangle's points + glm::vec3 p3 = av - glm::vec3(0.0f, dropAmount, 0.0f); int index3 = result.vertices.size(); result.vertices << p3; // add the new point to the result mesh