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
21ProgramObject MetavoxelSystem::_program;
22int MetavoxelSystem::_pointScaleLocation;
23
24MetavoxelSystem::MetavoxelSystem() :
25 _pointVisitor(_points),
26 _buffer(QOpenGLBuffer::VertexBuffer) {
27}
28
29MetavoxelSystem::~MetavoxelSystem() {
30 NodeList::getInstance()->removeHook(this);
31}
32
33void 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
56void 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
60void 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
79void 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
120void 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
127void 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
133void 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
139void MetavoxelSystem::removeClient(const QUuid& uuid) {
140 MetavoxelClient* client = _clients.take(uuid);
141 _clientsBySessionID.remove(client->getSessionID());
142 delete client;
143}
144
145void 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
157MetavoxelSystem::PointVisitor::PointVisitor(QVector<Point>& points) :
158 MetavoxelVisitor(QVector<AttributePointer>() <<
159 AttributeRegistry::getInstance()->getColorAttribute() <<
160 AttributeRegistry::getInstance()->getNormalAttribute()),
161 _points(points) {
162}
163
164bool 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
179static 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
186MetavoxelClient::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
201void 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
208void 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
216void MetavoxelClient::sendData(const QByteArray& data) {
217 NodeList::getInstance()->getNodeSocket().writeDatagram(data, _address.getAddress(), _address.getPort());
218}
219
220void 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
230void MetavoxelClient::clearReceiveRecordsBefore(int index) {
231 _receiveRecords.erase(_receiveRecords.begin(), _receiveRecords.begin() + index + 1);
232}
233
234void 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}