merge master into cleanup of legacy shapes

This commit is contained in:
Andrew Meadows 2015-08-03 11:19:29 -07:00
commit b00d47d62e
26 changed files with 208 additions and 76 deletions

View file

@ -70,7 +70,7 @@ void Agent::handleOctreePacket(QSharedPointer<NLPacket> packet, SharedNodePointe
// pull out the piggybacked packet and create a new QSharedPointer<NLPacket> for it
int piggyBackedSizeWithHeader = packet->getPayloadSize() - statsMessageLength;
std::unique_ptr<char> buffer = std::unique_ptr<char>(new char[piggyBackedSizeWithHeader]);
auto buffer = std::unique_ptr<char[]>(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<NLPacket> 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<EntityScriptingInterface>()->setEntityTree(NULL);
}
void Agent::sendPingRequests() {
auto nodeList = DependencyManager::get<NodeList>();
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);
});
}

View file

@ -58,11 +58,13 @@ private slots:
void handleAudioPacket(QSharedPointer<NLPacket> packet);
void handleOctreePacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
void handleJurisdictionPacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
void sendPingRequests();
private:
ScriptEngine _scriptEngine;
EntityEditPacketSender _entityEditSender;
EntityTreeHeadlessViewer _entityViewer;
QTimer* _pingTimer;
MixedAudioStream _receivedAudioStream;
float _lastReceivedAudioLoudness;

View file

@ -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);

View file

@ -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<char> buffer = std::unique_ptr<char>(new char[packetSizeWithHeader]);
auto buffer = std::unique_ptr<char[]>(new char[packetSizeWithHeader]);
_serverSocket.readDatagram(buffer.get(), packetSizeWithHeader,
sendingSockAddr.getAddressPointer(), sendingSockAddr.getPortPointer());

View file

@ -57,7 +57,7 @@ void OctreePacketProcessor::processPacket(QSharedPointer<NLPacket> packet, Share
if (piggybackBytes) {
// construct a new packet from the piggybacked one
std::unique_ptr<char> buffer = std::unique_ptr<char>(new char[piggybackBytes]);
auto buffer = std::unique_ptr<char[]>(new char[piggybackBytes]);
memcpy(buffer.get(), packet->getPayload() + statsMessageLength, piggybackBytes);
auto newPacket = NLPacket::fromReceivedPacket(std::move(buffer), piggybackBytes, packet->getSenderSockAddr());

View file

@ -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) {

View file

@ -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();
}
}

View file

@ -209,9 +209,6 @@ protected:
deleteLater();
}
private slots:
void audioStateChanged(QAudio::State state);
private:
void outputFormatChanged();

View file

@ -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<SittingPoint>& 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);

View file

@ -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<SittingPoint> _sittingPoints;
QStringList _textureNames;
glm::vec3 _naturalDimensions;
glm::vec3 _naturalPosition;
};
Q_DECLARE_METATYPE(EntityItemProperties);

View file

@ -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);
}
}

View file

@ -829,6 +829,56 @@ public:
std::vector<AttributeData> 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<gpu::Buffer>();
// QVector<int> quadIndices; // original indices from the FBX mesh
QVector<quint32> 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<int>& 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);

View file

@ -105,9 +105,10 @@ public:
class FBXMeshPart {
public:
QVector<int> quadIndices;
QVector<int> triangleIndices;
QVector<int> quadIndices; // original indices from the FBX mesh
QVector<int> 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.

View file

@ -213,9 +213,6 @@ enum Primitive {
TRIANGLES,
TRIANGLE_STRIP,
TRIANGLE_FAN,
QUADS,
QUAD_STRIP,
NUM_PRIMITIVES,
};

View file

@ -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] = {

View file

@ -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,

View file

@ -46,7 +46,7 @@ std::unique_ptr<NLPacket> NLPacket::create(PacketType::Value type, qint64 size)
return packet;
}
std::unique_ptr<NLPacket> NLPacket::fromReceivedPacket(std::unique_ptr<char> data, qint64 size,
std::unique_ptr<NLPacket> NLPacket::fromReceivedPacket(std::unique_ptr<char[]> 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<char> data, qint64 size, const HifiSockAddr& senderSockAddr) :
NLPacket::NLPacket(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& senderSockAddr) :
Packet(std::move(data), size, senderSockAddr)
{
adjustPayloadStartAndCapacity();

View file

@ -20,7 +20,7 @@ class NLPacket : public Packet {
Q_OBJECT
public:
static std::unique_ptr<NLPacket> create(PacketType::Value type, qint64 size = -1);
static std::unique_ptr<NLPacket> fromReceivedPacket(std::unique_ptr<char> data, qint64 size,
static std::unique_ptr<NLPacket> fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size,
const HifiSockAddr& senderSockAddr);
// Provided for convenience, try to limit use
static std::unique_ptr<NLPacket> createCopy(const NLPacket& other);
@ -45,7 +45,7 @@ protected:
NLPacket(PacketType::Value type);
NLPacket(PacketType::Value type, qint64 size);
NLPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
NLPacket(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& senderSockAddr);
NLPacket(const NLPacket& other);
void readSourceID();

View file

@ -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<char> buffer = std::unique_ptr<char>(new char[packetSizeWithHeader]);
auto buffer = std::unique_ptr<char[]>(new char[packetSizeWithHeader]);
// if we're supposed to drop this packet then break out here
if (_shouldDropPackets) {

View file

@ -31,7 +31,7 @@ std::unique_ptr<Packet> Packet::create(PacketType::Value type, qint64 size) {
return packet;
}
std::unique_ptr<Packet> Packet::fromReceivedPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr) {
std::unique_ptr<Packet> Packet::fromReceivedPacket(std::unique_ptr<char[]> 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<char> data, qint64 size, const HifiSockAddr& senderSockAddr) :
Packet::Packet(std::unique_ptr<char[]> 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<char>(new char[_packetSize]);
_packet = std::unique_ptr<char[]>(new char[_packetSize]);
memcpy(_packet.get(), other._packet.get(), _packetSize);
_payloadStart = _packet.get() + (other._payloadStart - other._packet.get());

View file

@ -27,7 +27,7 @@ public:
static const qint64 PACKET_WRITE_ERROR;
static std::unique_ptr<Packet> create(PacketType::Value type, qint64 size = -1);
static std::unique_ptr<Packet> fromReceivedPacket(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
static std::unique_ptr<Packet> fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& senderSockAddr);
// Provided for convenience, try to limit use
static std::unique_ptr<Packet> createCopy(const Packet& other);
@ -88,7 +88,7 @@ public:
protected:
Packet(PacketType::Value type, qint64 size);
Packet(std::unique_ptr<char> data, qint64 size, const HifiSockAddr& senderSockAddr);
Packet(std::unique_ptr<char[]> 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<char> _packet; // Allocated memory
std::unique_ptr<char[]> _packet; // Allocated memory
char* _payloadStart = nullptr; // Start of the payload
qint64 _payloadCapacity = 0; // Total capacity of the payload

View file

@ -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<gpu::Buffer>();
@ -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<gpu::Buffer>();
auto colorBuffer = std::make_shared<gpu::Buffer>();
auto streamFormat = std::make_shared<gpu::Stream::Format>();
auto stream = std::make_shared<gpu::BufferStream>();
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<gpu::Buffer>();
auto colorBuffer = std::make_shared<gpu::Buffer>();
auto streamFormat = std::make_shared<gpu::Stream::Format>();
auto stream = std::make_shared<gpu::BufferStream>();
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<gpu::Buffer>();
@ -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) {

View file

@ -240,6 +240,9 @@ QVector<JointState> 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) {

View file

@ -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<gpu::Buffer>();
_numVertices = 0;
_indicesBuffer = std::make_shared<gpu::Buffer>();
_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);
}

View file

@ -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;

View file

@ -12,6 +12,8 @@
#include <QVector>
#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