History

merge pull request 1446

Andrew Meadows committed 12 years ago

Commit d28ed701 parent f0460ba38 files · +2098 −262Browse files

Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 38 files). Show all

Unified · Split

interface/src/MetavoxelSystem.cpp+244−0
@@ -0,0 +1,244 @@
1+//
2+// MetavoxelSystem.cpp
3+// interface
4+//
5+// Created by Andrzej Kapolka on 12/10/13.
6+// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
7+//
8+
9+#include <QFile>
10+#include <QTextStream>
11+#include <QtDebug>
12+
13+#include <SharedUtil.h>
14+
15+#include <MetavoxelMessages.h>
16+#include <MetavoxelUtil.h>
17+
18+#include "Application.h"
19+#include "MetavoxelSystem.h"
20+
21+ProgramObject MetavoxelSystem::_program;
22+int MetavoxelSystem::_pointScaleLocation;
23+
24+MetavoxelSystem::MetavoxelSystem() :
25+ _pointVisitor(_points),
26+ _buffer(QOpenGLBuffer::VertexBuffer) {
27+}
28+
29+MetavoxelSystem::~MetavoxelSystem() {
30+ NodeList::getInstance()->removeHook(this);
31+}
32+
33+void MetavoxelSystem::init() {
34+ if (!_program.isLinked()) {
35+ switchToResourcesParentIfRequired();
36+ _program.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/metavoxel_point.vert");
37+ _program.link();
38+
39+ _pointScaleLocation = _program.uniformLocation("pointScale");
40+ }
41+
42+ NodeList::getInstance()->addHook(this);
43+
44+ AttributeRegistry::getInstance()->configureScriptEngine(&_scriptEngine);
45+
46+ QFile scriptFile("resources/scripts/sphere.js");
47+ scriptFile.open(QIODevice::ReadOnly);
48+ QScriptValue guideFunction = _scriptEngine.evaluate(QTextStream(&scriptFile).readAll());
49+ _data.setAttributeValue(MetavoxelPath(), AttributeValue(AttributeRegistry::getInstance()->getGuideAttribute(),
50+ encodeInline(PolymorphicDataPointer(new ScriptedMetavoxelGuide(guideFunction)))));
51+
52+ _buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
53+ _buffer.create();
54+}
55+
56+void MetavoxelSystem::processData(const QByteArray& data, const HifiSockAddr& sender) {
57+ QMetaObject::invokeMethod(this, "receivedData", Q_ARG(const QByteArray&, data), Q_ARG(const HifiSockAddr&, sender));
58+}
59+
60+void MetavoxelSystem::simulate(float deltaTime) {
61+ // simulate the clients
62+ foreach (MetavoxelClient* client, _clients) {
63+ client->simulate(deltaTime);
64+ }
65+
66+ _points.clear();
67+ _data.guide(_pointVisitor);
68+
69+ _buffer.bind();
70+ int bytes = _points.size() * sizeof(Point);
71+ if (_buffer.size() < bytes) {
72+ _buffer.allocate(_points.constData(), bytes);
73+ } else {
74+ _buffer.write(0, _points.constData(), bytes);
75+ }
76+ _buffer.release();
77+}
78+
79+void MetavoxelSystem::render() {
80+ int viewport[4];
81+ glGetIntegerv(GL_VIEWPORT, viewport);
82+ const int VIEWPORT_WIDTH_INDEX = 2;
83+ const int VIEWPORT_HEIGHT_INDEX = 3;
84+ float viewportWidth = viewport[VIEWPORT_WIDTH_INDEX];
85+ float viewportHeight = viewport[VIEWPORT_HEIGHT_INDEX];
86+ float viewportDiagonal = sqrtf(viewportWidth*viewportWidth + viewportHeight*viewportHeight);
87+ float worldDiagonal = glm::distance(Application::getInstance()->getViewFrustum()->getNearBottomLeft(),
88+ Application::getInstance()->getViewFrustum()->getNearTopRight());
89+
90+ _program.bind();
91+ _program.setUniformValue(_pointScaleLocation, viewportDiagonal *
92+ Application::getInstance()->getViewFrustum()->getNearClip() / worldDiagonal);
93+
94+ _buffer.bind();
95+
96+ Point* pt = 0;
97+ glVertexPointer(4, GL_FLOAT, sizeof(Point), &pt->vertex);
98+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Point), &pt->color);
99+ glNormalPointer(GL_BYTE, sizeof(Point), &pt->normal);
100+
101+ glEnableClientState(GL_VERTEX_ARRAY);
102+ glEnableClientState(GL_COLOR_ARRAY);
103+ glEnableClientState(GL_NORMAL_ARRAY);
104+
105+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
106+
107+ glDrawArrays(GL_POINTS, 0, _points.size());
108+
109+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
110+
111+ glDisableClientState(GL_VERTEX_ARRAY);
112+ glDisableClientState(GL_COLOR_ARRAY);
113+ glDisableClientState(GL_NORMAL_ARRAY);
114+
115+ _buffer.release();
116+
117+ _program.release();
118+}
119+
120+void MetavoxelSystem::nodeAdded(Node* node) {
121+ if (node->getType() == NODE_TYPE_METAVOXEL_SERVER) {
122+ QMetaObject::invokeMethod(this, "addClient", Q_ARG(const QUuid&, node->getUUID()),
123+ Q_ARG(const HifiSockAddr&, node->getLocalSocket()));
124+ }
125+}
126+
127+void MetavoxelSystem::nodeKilled(Node* node) {
128+ if (node->getType() == NODE_TYPE_METAVOXEL_SERVER) {
129+ QMetaObject::invokeMethod(this, "removeClient", Q_ARG(const QUuid&, node->getUUID()));
130+ }
131+}
132+
133+void MetavoxelSystem::addClient(const QUuid& uuid, const HifiSockAddr& address) {
134+ MetavoxelClient* client = new MetavoxelClient(address);
135+ _clients.insert(uuid, client);
136+ _clientsBySessionID.insert(client->getSessionID(), client);
137+}
138+
139+void MetavoxelSystem::removeClient(const QUuid& uuid) {
140+ MetavoxelClient* client = _clients.take(uuid);
141+ _clientsBySessionID.remove(client->getSessionID());
142+ delete client;
143+}
144+
145+void MetavoxelSystem::receivedData(const QByteArray& data, const HifiSockAddr& sender) {
146+ int headerPlusIDSize;
147+ QUuid sessionID = readSessionID(data, sender, headerPlusIDSize);
148+ if (sessionID.isNull()) {
149+ return;
150+ }
151+ MetavoxelClient* client = _clientsBySessionID.value(sessionID);
152+ if (client) {
153+ client->receivedData(data, sender);
154+ }
155+}
156+
157+MetavoxelSystem::PointVisitor::PointVisitor(QVector<Point>& points) :
158+ MetavoxelVisitor(QVector<AttributePointer>() <<
159+ AttributeRegistry::getInstance()->getColorAttribute() <<
160+ AttributeRegistry::getInstance()->getNormalAttribute()),
161+ _points(points) {
162+}
163+
164+bool MetavoxelSystem::PointVisitor::visit(const MetavoxelInfo& info) {
165+ if (!info.isLeaf) {
166+ return true;
167+ }
168+ QRgb color = info.attributeValues.at(0).getInlineValue<QRgb>();
169+ QRgb normal = info.attributeValues.at(1).getInlineValue<QRgb>();
170+ int alpha = qAlpha(color);
171+ if (alpha > 0) {
172+ Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),
173+ { qRed(color), qGreen(color), qBlue(color), alpha }, { qRed(normal), qGreen(normal), qBlue(normal) } };
174+ _points.append(point);
175+ }
176+ return false;
177+}
178+
179+static QByteArray createDatagramHeader(const QUuid& sessionID) {
180+ QByteArray header(MAX_PACKET_HEADER_BYTES, 0);
181+ populateTypeAndVersion(reinterpret_cast<unsigned char*>(header.data()), PACKET_TYPE_METAVOXEL_DATA);
182+ header += sessionID.toRfc4122();
183+ return header;
184+}
185+
186+MetavoxelClient::MetavoxelClient(const HifiSockAddr& address) :
187+ _address(address),
188+ _sessionID(QUuid::createUuid()),
189+ _sequencer(createDatagramHeader(_sessionID)),
190+ _data(new MetavoxelData()) {
191+
192+ connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&)));
193+ connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&)));
194+ connect(&_sequencer, SIGNAL(receiveAcknowledged(int)), SLOT(clearReceiveRecordsBefore(int)));
195+
196+ // insert the baseline receive record
197+ ReceiveRecord record = { 0, _data };
198+ _receiveRecords.append(record);
199+}
200+
201+void MetavoxelClient::simulate(float deltaTime) {
202+ Bitstream& out = _sequencer.startPacket();
203+ ClientStateMessage state = { Application::getInstance()->getCamera()->getPosition() };
204+ out << QVariant::fromValue(state);
205+ _sequencer.endPacket();
206+}
207+
208+void MetavoxelClient::receivedData(const QByteArray& data, const HifiSockAddr& sender) {
209+ // save the most recent sender
210+ _address = sender;
211+
212+ // process through sequencer
213+ _sequencer.receivedDatagram(data);
214+}
215+
216+void MetavoxelClient::sendData(const QByteArray& data) {
217+ NodeList::getInstance()->getNodeSocket().writeDatagram(data, _address.getAddress(), _address.getPort());
218+}
219+
220+void MetavoxelClient::readPacket(Bitstream& in) {
221+ QVariant message;
222+ in >> message;
223+ handleMessage(message, in);
224+
225+ // record the receipt
226+ ReceiveRecord record = { _sequencer.getIncomingPacketNumber(), _data };
227+ _receiveRecords.append(record);
228+}
229+
230+void MetavoxelClient::clearReceiveRecordsBefore(int index) {
231+ _receiveRecords.erase(_receiveRecords.begin(), _receiveRecords.begin() + index + 1);
232+}
233+
234+void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) {
235+ int userType = message.userType();
236+ if (userType == MetavoxelDeltaMessage::Type) {
237+ readDelta(_data, _receiveRecords.first().data, in);
238+
239+ } else if (userType == QMetaType::QVariantList) {
240+ foreach (const QVariant& element, message.toList()) {
241+ handleMessage(element, in);
242+ }
243+ }
244+}