mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 14:03:17 +02:00
Merge branch 'master' of git://github.com/highfidelity/hifi into audio-buffer-size
Conflicts: interface/src/Audio.cpp
This commit is contained in:
commit
defb2cbffd
158 changed files with 501 additions and 11918 deletions
|
@ -6,7 +6,7 @@ include_glm()
|
|||
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(
|
||||
audio avatars octree voxels gpu model fbx entities metavoxels
|
||||
audio avatars octree environment gpu model fbx entities metavoxels
|
||||
networking animation shared script-engine embedded-webserver
|
||||
physics
|
||||
)
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <ResourceCache.h>
|
||||
#include <SoundCache.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
#include <EntityScriptingInterface.h> // TODO: consider moving to scriptengine.h
|
||||
|
||||
|
@ -37,7 +36,6 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
|
|||
|
||||
Agent::Agent(const QByteArray& packet) :
|
||||
ThreadedAssignment(packet),
|
||||
_voxelEditSender(),
|
||||
_entityEditSender(),
|
||||
_receivedAudioStream(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES,
|
||||
InboundAudioStream::Settings(0, false, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, false,
|
||||
|
@ -48,7 +46,6 @@ Agent::Agent(const QByteArray& packet) :
|
|||
// be the parent of the script engine so it gets moved when we do
|
||||
_scriptEngine.setParent(this);
|
||||
|
||||
_scriptEngine.getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender);
|
||||
_scriptEngine.getEntityScriptingInterface()->setPacketSender(&_entityEditSender);
|
||||
}
|
||||
|
||||
|
@ -69,11 +66,6 @@ void Agent::readPendingDatagrams() {
|
|||
if (matchedNode) {
|
||||
// PacketType_JURISDICTION, first byte is the node type...
|
||||
switch (receivedPacket[headerBytes]) {
|
||||
case NodeType::VoxelServer:
|
||||
_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->
|
||||
queueReceivedPacket(matchedNode,receivedPacket);
|
||||
break;
|
||||
break;
|
||||
case NodeType::EntityServer:
|
||||
_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()->
|
||||
queueReceivedPacket(matchedNode, receivedPacket);
|
||||
|
@ -93,7 +85,6 @@ void Agent::readPendingDatagrams() {
|
|||
sourceNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
||||
} else if (datagramPacketType == PacketTypeOctreeStats
|
||||
|| datagramPacketType == PacketTypeVoxelData
|
||||
|| datagramPacketType == PacketTypeEntityData
|
||||
|| datagramPacketType == PacketTypeEntityErase
|
||||
) {
|
||||
|
@ -127,10 +118,6 @@ void Agent::readPendingDatagrams() {
|
|||
_entityViewer.processDatagram(mutablePacket, sourceNode);
|
||||
}
|
||||
|
||||
if (datagramPacketType == PacketTypeVoxelData) {
|
||||
_voxelViewer.processDatagram(mutablePacket, sourceNode);
|
||||
}
|
||||
|
||||
} else if (datagramPacketType == PacketTypeMixedAudio || datagramPacketType == PacketTypeSilentAudioFrame) {
|
||||
|
||||
_receivedAudioStream.parseData(receivedPacket);
|
||||
|
@ -168,7 +155,6 @@ void Agent::run() {
|
|||
nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet()
|
||||
<< NodeType::AudioMixer
|
||||
<< NodeType::AvatarMixer
|
||||
<< NodeType::VoxelServer
|
||||
<< NodeType::EntityServer
|
||||
);
|
||||
|
||||
|
@ -221,12 +207,6 @@ void Agent::run() {
|
|||
|
||||
_scriptEngine.registerGlobalObject("SoundCache", &SoundCache::getInstance());
|
||||
|
||||
_scriptEngine.registerGlobalObject("VoxelViewer", &_voxelViewer);
|
||||
// connect the VoxelViewer and the VoxelScriptingInterface to each other
|
||||
_voxelViewer.setJurisdictionListener(_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener());
|
||||
_voxelViewer.init();
|
||||
_scriptEngine.getVoxelsScriptingInterface()->setVoxelTree(_voxelViewer.getTree());
|
||||
|
||||
_scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer);
|
||||
_entityViewer.setJurisdictionListener(_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener());
|
||||
_entityViewer.init();
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#include <EntityTreeHeadlessViewer.h>
|
||||
#include <ScriptEngine.h>
|
||||
#include <ThreadedAssignment.h>
|
||||
#include <VoxelEditPacketSender.h>
|
||||
#include <VoxelTreeHeadlessViewer.h>
|
||||
|
||||
#include "MixedAudioStream.h"
|
||||
|
||||
|
@ -60,10 +58,7 @@ public slots:
|
|||
|
||||
private:
|
||||
ScriptEngine _scriptEngine;
|
||||
VoxelEditPacketSender _voxelEditSender;
|
||||
EntityEditPacketSender _entityEditSender;
|
||||
|
||||
VoxelTreeHeadlessViewer _voxelViewer;
|
||||
EntityTreeHeadlessViewer _entityViewer;
|
||||
|
||||
MixedAudioStream _receivedAudioStream;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "avatars/AvatarMixer.h"
|
||||
#include "metavoxels/MetavoxelServer.h"
|
||||
#include "entities/EntityServer.h"
|
||||
#include "voxels/VoxelServer.h"
|
||||
|
||||
ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) {
|
||||
QDataStream packetStream(packet);
|
||||
|
@ -35,8 +34,6 @@ ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet
|
|||
return new AvatarMixer(packet);
|
||||
case Assignment::AgentType:
|
||||
return new Agent(packet);
|
||||
case Assignment::VoxelServerType:
|
||||
return new VoxelServer(packet);
|
||||
case Assignment::MetavoxelServerType:
|
||||
return new MetavoxelServer(packet);
|
||||
case Assignment::EntityServerType:
|
||||
|
|
|
@ -148,7 +148,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
|
|||
qDebug() << " --- inside while loop ---";
|
||||
qDebug() << " maxSize=" << maxSize;
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() %c "
|
||||
"packetData=%p packetLength=%d voxelData=%p atByte=%d maxSize=%d",
|
||||
"packetData=%p packetLength=%d editData=%p atByte=%d maxSize=%d",
|
||||
packetType, packetData, packet.size(), editData, atByte, maxSize);
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
|
|||
processTime += thisProcessTime;
|
||||
lockWaitTime += thisLockWaitTime;
|
||||
|
||||
// skip to next voxel edit record in the packet
|
||||
// skip to next edit record in the packet
|
||||
editData += editDataBytesRead;
|
||||
atByte += editDataBytesRead;
|
||||
|
||||
|
@ -188,7 +188,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
|
|||
|
||||
if (debugProcessPacket) {
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() DONE LOOPING FOR %c "
|
||||
"packetData=%p packetLength=%d voxelData=%p atByte=%d",
|
||||
"packetData=%p packetLength=%d editData=%p atByte=%d",
|
||||
packetType, packetData, packet.size(), editData, atByte);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Created by Brad Hefta-Gaub on 8/21/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Threaded or non-threaded network packet processor for the voxel-server
|
||||
// Threaded or non-threaded network packet processor for octree servers
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -53,7 +53,7 @@ typedef QHash<QUuid, SingleSenderStats>::iterator NodeToSenderStatsMapIterator;
|
|||
typedef QHash<QUuid, SingleSenderStats>::const_iterator NodeToSenderStatsMapConstIterator;
|
||||
|
||||
|
||||
/// Handles processing of incoming network packets for the voxel-server. As with other ReceivedPacketProcessor classes
|
||||
/// Handles processing of incoming network packets for the octee servers. As with other ReceivedPacketProcessor classes
|
||||
/// the user is responsible for reading inbound packets and adding them to the processing queue by calling queueReceivedPacket()
|
||||
class OctreeInboundPacketProcessor : public ReceivedPacketProcessor {
|
||||
Q_OBJECT
|
||||
|
@ -89,7 +89,7 @@ private:
|
|||
|
||||
private:
|
||||
void trackInboundPacket(const QUuid& nodeUUID, unsigned short int sequence, quint64 transitTime,
|
||||
int voxelsInPacket, quint64 processTime, quint64 lockWaitTime);
|
||||
int elementsInPacket, quint64 processTime, quint64 lockWaitTime);
|
||||
|
||||
OctreeServer* _myServer;
|
||||
int _receivedPacketCount;
|
||||
|
|
|
@ -147,10 +147,10 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
|||
int statsMessageLength = nodeData->stats.getStatsMessageLength();
|
||||
int piggyBackSize = nodeData->getPacketLength() + statsMessageLength;
|
||||
|
||||
// If the size of the stats message and the voxel message will fit in a packet, then piggyback them
|
||||
// If the size of the stats message and the octree message will fit in a packet, then piggyback them
|
||||
if (piggyBackSize < MAX_PACKET_SIZE) {
|
||||
|
||||
// copy voxel message to back of stats message
|
||||
// copy octree message to back of stats message
|
||||
memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength());
|
||||
statsMessageLength += nodeData->getPacketLength();
|
||||
|
||||
|
@ -240,7 +240,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes
|
|||
} else {
|
||||
// If there's actually a packet waiting, then send it.
|
||||
if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) {
|
||||
// just send the voxel packet
|
||||
// just send the octree packet
|
||||
OctreeServer::didCallWriteDatagram(this);
|
||||
NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node);
|
||||
packetSent = true;
|
||||
|
@ -430,7 +430,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
|||
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
|
||||
CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP;
|
||||
|
||||
float voxelSizeScale = nodeData->getOctreeSizeScale();
|
||||
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
||||
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
|
||||
|
||||
int boundaryLevelAdjust = boundaryLevelAdjustClient + (viewFrustumChanged && nodeData->getWantLowResMoving()
|
||||
|
@ -438,7 +438,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
|||
|
||||
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor,
|
||||
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
|
||||
wantOcclusionCulling, coverageMap, boundaryLevelAdjust, voxelSizeScale,
|
||||
wantOcclusionCulling, coverageMap, boundaryLevelAdjust, octreeSizeScale,
|
||||
nodeData->getLastTimeBagEmpty(),
|
||||
isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
|
||||
&nodeData->extraEncodeData);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Created by Brad Hefta-Gaub on 8/21/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Threaded or non-threaded object for sending voxels to a client
|
||||
// Threaded or non-threaded object for sending octree data packets to a client
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
class OctreeServer;
|
||||
|
||||
/// Threaded processor for sending voxel packets to a single client
|
||||
/// Threaded processor for sending octree packets to a single client
|
||||
class OctreeSendThread : public GenericThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -358,7 +358,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
statsString += "Uptime: " + getUptime();
|
||||
statsString += "\r\n\r\n";
|
||||
|
||||
// display voxel file load time
|
||||
// display octree file load time
|
||||
if (isInitialLoadComplete()) {
|
||||
if (isPersistEnabled()) {
|
||||
statsString += QString("%1 File Persist Enabled...\r\n").arg(getMyServerName());
|
||||
|
@ -373,7 +373,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
statsString += "\r\n";
|
||||
|
||||
} else {
|
||||
statsString += "Voxels not yet loaded...\r\n";
|
||||
statsString += "Octree file not yet loaded...\r\n";
|
||||
}
|
||||
|
||||
statsString += "\r\n\r\n";
|
||||
|
@ -712,7 +712,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
}
|
||||
|
||||
statsString += QString().sprintf("Element Node Memory Usage: %8.2f %s\r\n",
|
||||
OctreeElement::getVoxelMemoryUsage() / memoryScale, memoryScaleLabel);
|
||||
OctreeElement::getOctreeMemoryUsage() / memoryScale, memoryScaleLabel);
|
||||
statsString += QString().sprintf("Octcode Memory Usage: %8.2f %s\r\n",
|
||||
OctreeElement::getOctcodeMemoryUsage() / memoryScale, memoryScaleLabel);
|
||||
statsString += QString().sprintf("External Children Memory Usage: %8.2f %s\r\n",
|
||||
|
|
|
@ -121,7 +121,7 @@ public:
|
|||
void forceNodeShutdown(SharedNodePointer node);
|
||||
|
||||
public slots:
|
||||
/// runs the voxel server assignment
|
||||
/// runs the octree server assignment
|
||||
void run();
|
||||
void nodeAdded(SharedNodePointer node);
|
||||
void nodeKilled(SharedNodePointer node);
|
||||
|
|
|
@ -19,6 +19,6 @@
|
|||
const int MAX_FILENAME_LENGTH = 1024;
|
||||
const int INTERVALS_PER_SECOND = 60;
|
||||
const int OCTREE_SEND_INTERVAL_USECS = (1000 * 1000)/INTERVALS_PER_SECOND;
|
||||
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels
|
||||
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for sending octree elements
|
||||
|
||||
#endif // hifi_OctreeServerConsts_h
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// VoxelNodeData.h
|
||||
// assignment-client/src/voxels
|
||||
//
|
||||
// Created by Stephen Birarda on 3/21/13.
|
||||
// Copyright 2014 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_VoxelNodeData_h
|
||||
#define hifi_VoxelNodeData_h
|
||||
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include "../octree/OctreeQueryNode.h"
|
||||
|
||||
class VoxelNodeData : public OctreeQueryNode {
|
||||
public:
|
||||
VoxelNodeData() : OctreeQueryNode() { }
|
||||
virtual PacketType getMyPacketType() const { return PacketTypeVoxelData; }
|
||||
};
|
||||
|
||||
#endif // hifi_VoxelNodeData_h
|
|
@ -1,102 +0,0 @@
|
|||
//
|
||||
// VoxelServer.cpp
|
||||
// assignment-client/src/voxels
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 9/16/13.
|
||||
// Copyright 2013 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 <VoxelTree.h>
|
||||
|
||||
#include "VoxelServer.h"
|
||||
#include "VoxelServerConsts.h"
|
||||
#include "VoxelNodeData.h"
|
||||
|
||||
const char* VOXEL_SERVER_NAME = "Voxel";
|
||||
const char* VOXEL_SERVER_LOGGING_TARGET_NAME = "voxel-server";
|
||||
const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo";
|
||||
|
||||
VoxelServer::VoxelServer(const QByteArray& packet) : OctreeServer(packet) {
|
||||
// nothing special to do here...
|
||||
}
|
||||
|
||||
VoxelServer::~VoxelServer() {
|
||||
// nothing special to do here...
|
||||
}
|
||||
|
||||
OctreeQueryNode* VoxelServer::createOctreeQueryNode() {
|
||||
return new VoxelNodeData();
|
||||
}
|
||||
|
||||
Octree* VoxelServer::createTree() {
|
||||
return new VoxelTree(true);
|
||||
}
|
||||
|
||||
bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) {
|
||||
bool shouldSendEnvironments = _sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, OCTREE_SEND_INTERVAL_USECS);
|
||||
return shouldSendEnvironments;
|
||||
}
|
||||
|
||||
int VoxelServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) {
|
||||
|
||||
unsigned char* copyAt = _tempOutputBuffer;
|
||||
|
||||
int numBytesPacketHeader = populatePacketHeader(reinterpret_cast<char*>(_tempOutputBuffer), PacketTypeEnvironmentData);
|
||||
copyAt += numBytesPacketHeader;
|
||||
int envPacketLength = numBytesPacketHeader;
|
||||
|
||||
// pack in flags
|
||||
OCTREE_PACKET_FLAGS flags = 0;
|
||||
OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt;
|
||||
*flagsAt = flags;
|
||||
copyAt += sizeof(OCTREE_PACKET_FLAGS);
|
||||
envPacketLength += sizeof(OCTREE_PACKET_FLAGS);
|
||||
|
||||
// pack in sequence number
|
||||
OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt;
|
||||
*sequenceAt = queryNode->getSequenceNumber();
|
||||
copyAt += sizeof(OCTREE_PACKET_SEQUENCE);
|
||||
envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE);
|
||||
|
||||
// pack in timestamp
|
||||
OCTREE_PACKET_SENT_TIME now = usecTimestampNow();
|
||||
OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt;
|
||||
*timeAt = now;
|
||||
copyAt += sizeof(OCTREE_PACKET_SENT_TIME);
|
||||
envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME);
|
||||
|
||||
int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount();
|
||||
|
||||
for (int i = 0; i < environmentsToSend; i++) {
|
||||
envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength);
|
||||
}
|
||||
|
||||
NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node));
|
||||
queryNode->packetSent(_tempOutputBuffer, envPacketLength);
|
||||
packetsSent = 1;
|
||||
|
||||
return envPacketLength;
|
||||
}
|
||||
|
||||
|
||||
void VoxelServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) {
|
||||
// should we send environments? Default is yes, but this command line suppresses sending
|
||||
readOptionBool(QString("sendEnvironments"), settingsSectionObject, _sendEnvironments);
|
||||
bool dontSendEnvironments = !_sendEnvironments;
|
||||
if (dontSendEnvironments) {
|
||||
qDebug("Sending environments suppressed...");
|
||||
} else {
|
||||
// should we send environments? Default is yes, but this command line suppresses sending
|
||||
//const char* MINIMAL_ENVIRONMENT = "--minimalEnvironment";
|
||||
//_sendMinimalEnvironment = cmdOptionExists(_argc, _argv, MINIMAL_ENVIRONMENT);
|
||||
|
||||
readOptionBool(QString("minimalEnvironment"), settingsSectionObject, _sendMinimalEnvironment);
|
||||
qDebug("Using Minimal Environment=%s", debug::valueOf(_sendMinimalEnvironment));
|
||||
}
|
||||
qDebug("Sending environments=%s", debug::valueOf(_sendEnvironments));
|
||||
|
||||
NodeList::getInstance()->addNodeTypeToInterestSet(NodeType::AnimationServer);
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// VoxelServer.h
|
||||
// assignment-client/src/voxels
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/21/13.
|
||||
// Copyright 2013 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_VoxelServer_h
|
||||
#define hifi_VoxelServer_h
|
||||
|
||||
#include <QStringList>
|
||||
#include <QDateTime>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
#include <ThreadedAssignment.h>
|
||||
#include <EnvironmentData.h>
|
||||
|
||||
#include "../octree/OctreeServer.h"
|
||||
|
||||
#include "VoxelServerConsts.h"
|
||||
|
||||
/// Handles assignments of type VoxelServer - sending voxels to various clients.
|
||||
class VoxelServer : public OctreeServer {
|
||||
public:
|
||||
VoxelServer(const QByteArray& packet);
|
||||
~VoxelServer();
|
||||
|
||||
bool wantSendEnvironments() const { return _sendEnvironments; }
|
||||
bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; }
|
||||
EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; }
|
||||
int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); }
|
||||
|
||||
// Subclasses must implement these methods
|
||||
virtual OctreeQueryNode* createOctreeQueryNode();
|
||||
virtual char getMyNodeType() const { return NodeType::VoxelServer; }
|
||||
virtual PacketType getMyQueryMessageType() const { return PacketTypeVoxelQuery; }
|
||||
virtual const char* getMyServerName() const { return VOXEL_SERVER_NAME; }
|
||||
virtual const char* getMyLoggingServerTargetName() const { return VOXEL_SERVER_LOGGING_TARGET_NAME; }
|
||||
virtual const char* getMyDefaultPersistFilename() const { return LOCAL_VOXELS_PERSIST_FILE; }
|
||||
virtual PacketType getMyEditNackType() const { return PacketTypeVoxelEditNack; }
|
||||
virtual QString getMyDomainSettingsKey() const { return QString("voxel_server_settings"); }
|
||||
|
||||
// subclass may implement these method
|
||||
virtual bool hasSpecialPacketToSend(const SharedNodePointer& node);
|
||||
virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent);
|
||||
|
||||
protected:
|
||||
virtual Octree* createTree();
|
||||
virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject);
|
||||
|
||||
private:
|
||||
bool _sendEnvironments;
|
||||
bool _sendMinimalEnvironment;
|
||||
EnvironmentData _environmentData[3];
|
||||
unsigned char _tempOutputBuffer[MAX_PACKET_SIZE];
|
||||
};
|
||||
|
||||
#endif // hifi_VoxelServer_h
|
|
@ -1,21 +0,0 @@
|
|||
//
|
||||
// VoxelServerConsts.h
|
||||
// assignment-client/src/voxels
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/21/13.
|
||||
// Copyright 2013 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_VoxelServerConsts_h
|
||||
#define hifi_VoxelServerConsts_h
|
||||
|
||||
extern const char* VOXEL_SERVER_NAME;
|
||||
extern const char* VOXEL_SERVER_LOGGING_TARGET_NAME;
|
||||
extern const char* LOCAL_VOXELS_PERSIST_FILE;
|
||||
|
||||
const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000;
|
||||
|
||||
#endif // hifi_VoxelServerConsts_h
|
|
@ -410,99 +410,5 @@
|
|||
"advanced": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "voxel_server_settings",
|
||||
"label": "Voxel Server Settings",
|
||||
"assignment-types": [3],
|
||||
"settings": [
|
||||
{
|
||||
"name": "persistFilename",
|
||||
"label": "Persistant Filename",
|
||||
"help": "the filename for your voxels",
|
||||
"placeholder": "resources/voxels.svo",
|
||||
"default": "resources/voxels.svo",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "persistInterval",
|
||||
"label": "Persist Interval",
|
||||
"help": "Interval between persist checks in msecs.",
|
||||
"placeholder": "30000",
|
||||
"default": "30000",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "NoPersist",
|
||||
"type": "checkbox",
|
||||
"help": "Don't persist your voxels to a file.",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "backupExtensionFormat",
|
||||
"label": "Backup File Extension Format:",
|
||||
"help": "Format used to create the extension for the backup of your persisted voxels.",
|
||||
"placeholder": ".backup.%Y-%m-%d.%H:%M:%S.%z",
|
||||
"default": ".backup.%Y-%m-%d.%H:%M:%S.%z",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "backupInterval",
|
||||
"label": "Backup Interval",
|
||||
"help": "Interval between backup checks in msecs.",
|
||||
"placeholder": "1800000",
|
||||
"default": "1800000",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "NoBackup",
|
||||
"type": "checkbox",
|
||||
"help": "Don't regularly backup your persisted voxels to a backup file.",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "statusHost",
|
||||
"label": "Status Hostname",
|
||||
"help": "host name or IP address of the server for accessing the status page",
|
||||
"placeholder": "",
|
||||
"default": "",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "statusPort",
|
||||
"label": "Status Port",
|
||||
"help": "port of the server for accessing the status page",
|
||||
"placeholder": "",
|
||||
"default": "",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "clockSkew",
|
||||
"label": "Clock Skew",
|
||||
"help": "Number of msecs to skew the server clock by to test clock skew",
|
||||
"placeholder": "0",
|
||||
"default": "0",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "sendEnvironments",
|
||||
"type": "checkbox",
|
||||
"help": "send environmental data",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "minimalEnvironment",
|
||||
"type": "checkbox",
|
||||
"help": "send minimal environmental data if sending environmental data",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
]
|
|
@ -550,7 +550,8 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Ass
|
|||
defaultedType != Assignment::AllTypes;
|
||||
defaultedType = static_cast<Assignment::Type>(static_cast<int>(defaultedType) + 1)) {
|
||||
if (!excludedTypes.contains(defaultedType)
|
||||
&& defaultedType != Assignment::UNUSED
|
||||
&& defaultedType != Assignment::UNUSED_0
|
||||
&& defaultedType != Assignment::UNUSED_1
|
||||
&& defaultedType != Assignment::AgentType) {
|
||||
// type has not been set from a command line or config file config, use the default
|
||||
// by clearing whatever exists and writing a single default assignment with no payload
|
||||
|
@ -561,7 +562,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Ass
|
|||
}
|
||||
|
||||
const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer
|
||||
<< NodeType::AvatarMixer << NodeType::VoxelServer << NodeType::EntityServer
|
||||
<< NodeType::AvatarMixer << NodeType::EntityServer
|
||||
<< NodeType::MetavoxelServer;
|
||||
|
||||
void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSockAddr& senderSockAddr) {
|
||||
|
|
|
@ -145,13 +145,9 @@ function sendCommand(id, action) {
|
|||
return;
|
||||
}
|
||||
|
||||
Voxels.setVoxel(controlVoxelPosition.x + id * controlVoxelSize,
|
||||
controlVoxelPosition.y,
|
||||
controlVoxelPosition.z,
|
||||
controlVoxelSize,
|
||||
COLORS[action].red,
|
||||
COLORS[action].green,
|
||||
COLORS[action].blue);
|
||||
// TODO: Fix this to use some mechanism other than voxels
|
||||
//Voxels.setVoxel(controlVoxelPosition.x + id * controlVoxelSize, controlVoxelPosition.y, controlVoxelPosition.z,
|
||||
// controlVoxelSize, COLORS[action].red, COLORS[action].green, COLORS[action].blue);
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
|
|
|
@ -82,10 +82,9 @@ function getAction(controlVoxel) {
|
|||
if (controlVoxel.red === COLORS[i].red &&
|
||||
controlVoxel.green === COLORS[i].green &&
|
||||
controlVoxel.blue === COLORS[i].blue) {
|
||||
Voxels.eraseVoxel(controlVoxelPosition.x,
|
||||
controlVoxelPosition.y,
|
||||
controlVoxelPosition.z,
|
||||
controlVoxelSize);
|
||||
|
||||
// TODO: Fix this to use some mechanism other than voxels
|
||||
//Voxels.eraseVoxel(controlVoxelPosition.x, controlVoxelPosition.y, controlVoxelPosition.z, controlVoxelSize);
|
||||
return parseInt(i);
|
||||
}
|
||||
}
|
||||
|
@ -101,10 +100,9 @@ function update(event) {
|
|||
return;
|
||||
}
|
||||
|
||||
var controlVoxel = Voxels.getVoxelAt(controlVoxelPosition.x,
|
||||
controlVoxelPosition.y,
|
||||
controlVoxelPosition.z,
|
||||
controlVoxelSize);
|
||||
// TODO: Fix this to use some mechanism other than voxels
|
||||
// Voxels.getVoxelAt(controlVoxelPosition.x, controlVoxelPosition.y, controlVoxelPosition.z, controlVoxelSize);
|
||||
var controlVoxel = false;
|
||||
var action = getAction(controlVoxel);
|
||||
|
||||
switch(action) {
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
//
|
||||
// addVoxelOnMouseClickExample.js
|
||||
// examples
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 2/6/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This is an example script that demonstrates use of the Camera and Voxels class to implement
|
||||
// clicking on a voxel and adding a new voxel on the clicked on face
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
function mousePressEvent(event) {
|
||||
print("mousePressEvent event.x,y=" + event.x + ", " + event.y);
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
if (intersection.intersects) {
|
||||
|
||||
// Note: due to the current C++ "click on voxel" behavior, these values may be the animated color for the voxel
|
||||
print("clicked on voxel.red/green/blue=" + intersection.voxel.red + ", "
|
||||
+ intersection.voxel.green + ", " + intersection.voxel.blue);
|
||||
print("clicked on voxel.x/y/z/s=" + intersection.voxel.x + ", "
|
||||
+ intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s);
|
||||
print("clicked on face=" + intersection.face);
|
||||
print("clicked on distance=" + intersection.distance);
|
||||
|
||||
var newVoxel = {
|
||||
x: intersection.voxel.x,
|
||||
y: intersection.voxel.y,
|
||||
z: intersection.voxel.z,
|
||||
s: intersection.voxel.s,
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 255 };
|
||||
|
||||
if (intersection.face == "MIN_X_FACE") {
|
||||
newVoxel.x -= newVoxel.s;
|
||||
} else if (intersection.face == "MAX_X_FACE") {
|
||||
newVoxel.x += newVoxel.s;
|
||||
} else if (intersection.face == "MIN_Y_FACE") {
|
||||
newVoxel.y -= newVoxel.s;
|
||||
} else if (intersection.face == "MAX_Y_FACE") {
|
||||
newVoxel.y += newVoxel.s;
|
||||
} else if (intersection.face == "MIN_Z_FACE") {
|
||||
newVoxel.z -= newVoxel.s;
|
||||
} else if (intersection.face == "MAX_Z_FACE") {
|
||||
newVoxel.z += newVoxel.s;
|
||||
}
|
||||
|
||||
print("Voxels.setVoxel("+newVoxel.x + ", "
|
||||
+ newVoxel.y + ", " + newVoxel.z + ", " + newVoxel.s + ", "
|
||||
+ newVoxel.red + ", " + newVoxel.green + ", " + newVoxel.blue + ")" );
|
||||
|
||||
Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
|
||||
function scriptEnding() {
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
|
@ -79,7 +79,7 @@ function addButterfly() {
|
|||
rotation: Quat.fromPitchYawRollDegrees(-80 + Math.random() * 20, Math.random() * 360.0, 0.0),
|
||||
velocity: { x: 0, y: 0, z: 0 },
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
damping: 0.9999,
|
||||
damping: 0.00001,
|
||||
dimensions: dimensions,
|
||||
color: color,
|
||||
animationURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/content/butterfly/butterfly.fbx",
|
||||
|
@ -138,4 +138,4 @@ Script.scriptEnding.connect(function() {
|
|||
for (var i = 0; i < numButterflies; i++) {
|
||||
Entities.deleteEntity(butterflies[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var damping = 0.9;
|
||||
var damping = 0.001;
|
||||
var yaw = 0.0;
|
||||
var pitch = 0.0;
|
||||
var roll = 0.0;
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
//
|
||||
// clipboardExample.js
|
||||
// examples
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 1/28/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This is an example script that demonstrates use of the Clipboard class
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var selectedVoxel = { x: 0, y: 0, z: 0, s: 0 };
|
||||
var selectedSize = 4;
|
||||
|
||||
function setupMenus() {
|
||||
// hook up menus
|
||||
Menu.menuItemEvent.connect(menuItemEvent);
|
||||
|
||||
// delete the standard application menu item
|
||||
Menu.removeMenuItem("Edit", "Cut");
|
||||
Menu.removeMenuItem("Edit", "Copy");
|
||||
Menu.removeMenuItem("Edit", "Paste");
|
||||
Menu.removeMenuItem("Edit", "Delete");
|
||||
Menu.removeMenuItem("Edit", "Nudge");
|
||||
Menu.removeMenuItem("Edit", "Replace from File");
|
||||
Menu.removeMenuItem("File", "Export Voxels");
|
||||
Menu.removeMenuItem("File", "Import Voxels");
|
||||
|
||||
// delete the standard application menu item
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Cut", shortcutKey: "CTRL+X", afterItem: "Voxels" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Copy", shortcutKey: "CTRL+C", afterItem: "Cut" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste", shortcutKey: "CTRL+V", afterItem: "Copy" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Nudge", shortcutKey: "CTRL+N", afterItem: "Paste" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Replace from File", shortcutKey: "CTRL+R", afterItem: "Nudge" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", shortcutKeyEvent: { text: "backspace" }, afterItem: "Nudge" });
|
||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Voxels", shortcutKey: "CTRL+E", afterItem: "Voxels" });
|
||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Voxels", shortcutKey: "CTRL+I", afterItem: "Export Voxels" });
|
||||
}
|
||||
|
||||
function menuItemEvent(menuItem) {
|
||||
var debug = true;
|
||||
if (debug) {
|
||||
print("menuItemEvent " + menuItem);
|
||||
}
|
||||
|
||||
// Note: this sample uses Alt+ as the key codes for these clipboard items
|
||||
if (menuItem == "Copy") {
|
||||
print("copying...");
|
||||
Clipboard.copyVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s);
|
||||
}
|
||||
if (menuItem == "Cut") {
|
||||
print("cutting...");
|
||||
Clipboard.cutVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s);
|
||||
}
|
||||
if (menuItem == "Paste") {
|
||||
print("pasting...");
|
||||
Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s);
|
||||
}
|
||||
if (menuItem == "Delete") {
|
||||
print("deleting...");
|
||||
Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s);
|
||||
}
|
||||
if (menuItem == "Export Voxels") {
|
||||
print("export");
|
||||
Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s);
|
||||
}
|
||||
if (menuItem == "Import Voxels") {
|
||||
print("import");
|
||||
Clipboard.importVoxels();
|
||||
}
|
||||
if (menuItem == "Nudge") {
|
||||
print("nudge");
|
||||
Clipboard.nudgeVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s, { x: -1, y: 0, z: 0 });
|
||||
}
|
||||
if (menuItem == "Replace from File") {
|
||||
var filename = Window.browse("Select file to load replacement", "", "Voxel Files (*.png *.svo *.schematic)");
|
||||
if (filename) {
|
||||
Clipboard.importVoxel(filename, selectedVoxel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var selectCube = Overlays.addOverlay("cube", {
|
||||
position: { x: 0, y: 0, z: 0},
|
||||
size: selectedSize,
|
||||
color: { red: 255, green: 255, blue: 0},
|
||||
alpha: 1,
|
||||
solid: false,
|
||||
visible: false,
|
||||
lineWidth: 4
|
||||
});
|
||||
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
|
||||
var debug = false;
|
||||
if (debug) {
|
||||
print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y);
|
||||
print("called Camera.computePickRay()");
|
||||
print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z);
|
||||
print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z);
|
||||
}
|
||||
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
|
||||
if (intersection.intersects) {
|
||||
if (debug) {
|
||||
print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", "
|
||||
+ intersection.voxel.green + ", " + intersection.voxel.blue);
|
||||
print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", "
|
||||
+ intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s);
|
||||
print("intersection face=" + intersection.face);
|
||||
print("intersection distance=" + intersection.distance);
|
||||
print("intersection intersection.x/y/z=" + intersection.intersection.x + ", "
|
||||
+ intersection.intersection.y + ", " + intersection.intersection.z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var x = Math.floor(intersection.voxel.x / selectedSize) * selectedSize;
|
||||
var y = Math.floor(intersection.voxel.y / selectedSize) * selectedSize;
|
||||
var z = Math.floor(intersection.voxel.z / selectedSize) * selectedSize;
|
||||
selectedVoxel = { x: x, y: y, z: z, s: selectedSize };
|
||||
Overlays.editOverlay(selectCube, { position: selectedVoxel, size: selectedSize, visible: true } );
|
||||
} else {
|
||||
Overlays.editOverlay(selectCube, { visible: false } );
|
||||
selectedVoxel = { x: 0, y: 0, z: 0, s: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
|
||||
function wheelEvent(event) {
|
||||
var debug = false;
|
||||
if (debug) {
|
||||
print("wheelEvent");
|
||||
print(" event.x,y=" + event.x + ", " + event.y);
|
||||
print(" event.delta=" + event.delta);
|
||||
print(" event.orientation=" + event.orientation);
|
||||
print(" event.isLeftButton=" + event.isLeftButton);
|
||||
print(" event.isRightButton=" + event.isRightButton);
|
||||
print(" event.isMiddleButton=" + event.isMiddleButton);
|
||||
print(" event.isShifted=" + event.isShifted);
|
||||
print(" event.isControl=" + event.isControl);
|
||||
print(" event.isMeta=" + event.isMeta);
|
||||
print(" event.isAlt=" + event.isAlt);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.wheelEvent.connect(wheelEvent);
|
||||
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(selectCube);
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
setupMenus();
|
|
@ -1720,7 +1720,7 @@ var ModelImporter = function (opts) {
|
|||
this.mouseMoveEvent = function (event) {
|
||||
if (self._importing) {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
var intersection = false; //Voxels.findRayIntersection(pickRay);
|
||||
|
||||
var distance = 2;// * self._scale;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,648 +0,0 @@
|
|||
//
|
||||
// fallingSand.js
|
||||
// examples
|
||||
//
|
||||
// Created by Ben Arnold on 7/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This sample script allows the user to place sand voxels that will undergo
|
||||
// cellular automata physics.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("libraries/globals.js");
|
||||
|
||||
var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting
|
||||
var previewLineWidth = 2.0;
|
||||
|
||||
var voxelSize = 1;
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||
|
||||
var MAX_VOXEL_SCALE_POWER = 5;
|
||||
var MIN_VOXEL_SCALE_POWER = -8;
|
||||
var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER);
|
||||
var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER);
|
||||
|
||||
|
||||
var linePreviewTop = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 0, blue: 255},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
var linePreviewBottom = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 0, blue: 255},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
var linePreviewLeft = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 0, blue: 255},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
var linePreviewRight = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 0, blue: 255},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
|
||||
var UIColor = { red: 119, green: 103, blue: 53};
|
||||
var activeUIColor = { red: 234, green: 206, blue: 106};
|
||||
|
||||
var toolHeight = 50;
|
||||
var toolWidth = 50;
|
||||
|
||||
var editToolsOn = true;
|
||||
|
||||
var voxelToolSelected = false;
|
||||
|
||||
var scaleSelectorWidth = 144;
|
||||
var scaleSelectorHeight = 37;
|
||||
|
||||
var scaleSelectorX = windowDimensions.x / 5.0;
|
||||
var scaleSelectorY = windowDimensions.y - scaleSelectorHeight;
|
||||
|
||||
var voxelTool = Overlays.addOverlay("image", {
|
||||
x: scaleSelectorX + scaleSelectorWidth + 1, y: windowDimensions.y - toolHeight, width: toolWidth, height: toolHeight,
|
||||
subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight },
|
||||
imageURL: toolIconUrl + "voxel-tool.svg",
|
||||
visible: editToolsOn,
|
||||
color: UIColor,
|
||||
alpha: 0.9
|
||||
});
|
||||
|
||||
var copyScale = true;
|
||||
function ScaleSelector() {
|
||||
this.x = scaleSelectorX;
|
||||
this.y = scaleSelectorY;
|
||||
this.width = scaleSelectorWidth;
|
||||
this.height = scaleSelectorHeight;
|
||||
|
||||
this.displayPower = false;
|
||||
this.scale = 1.0;
|
||||
this.power = 0;
|
||||
|
||||
this.FIRST_PART = this.width * 40.0 / 100.0;
|
||||
this.SECOND_PART = this.width * 37.0 / 100.0;
|
||||
|
||||
this.buttonsOverlay = Overlays.addOverlay("image", {
|
||||
x: this.x, y: this.y,
|
||||
width: this.width, height: this.height,
|
||||
//subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight },
|
||||
imageURL: toolIconUrl + "voxel-size-selector.svg",
|
||||
alpha: 0.9,
|
||||
visible: editToolsOn,
|
||||
color: activeUIColor
|
||||
});
|
||||
this.textOverlay = Overlays.addOverlay("text", {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
width: this.SECOND_PART, height: this.height,
|
||||
topMargin: 13,
|
||||
text: this.scale.toString(),
|
||||
backgroundAlpha: 0.0,
|
||||
visible: editToolsOn,
|
||||
color: activeUIColor
|
||||
});
|
||||
this.powerOverlay = Overlays.addOverlay("text", {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
width: this.SECOND_PART, height: this.height,
|
||||
leftMargin: 28,
|
||||
text: this.power.toString(),
|
||||
backgroundAlpha: 0.0,
|
||||
visible: false,
|
||||
color: activeUIColor
|
||||
});
|
||||
this.setScale = function(scale) {
|
||||
if (scale > MAX_VOXEL_SCALE) {
|
||||
scale = MAX_VOXEL_SCALE;
|
||||
}
|
||||
if (scale < MIN_VOXEL_SCALE) {
|
||||
scale = MIN_VOXEL_SCALE;
|
||||
}
|
||||
|
||||
this.scale = scale;
|
||||
this.power = Math.floor(Math.log(scale) / Math.log(2));
|
||||
this.update();
|
||||
}
|
||||
|
||||
this.show = function(doShow) {
|
||||
Overlays.editOverlay(this.buttonsOverlay, {visible: doShow});
|
||||
Overlays.editOverlay(this.textOverlay, {visible: doShow});
|
||||
Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower});
|
||||
}
|
||||
|
||||
this.move = function() {
|
||||
this.x = swatchesX + swatchesWidth;
|
||||
this.y = swatchesY;
|
||||
|
||||
Overlays.editOverlay(this.buttonsOverlay, {
|
||||
x: this.x, y: this.y,
|
||||
});
|
||||
Overlays.editOverlay(this.textOverlay, {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
});
|
||||
Overlays.editOverlay(this.powerOverlay, {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.switchDisplay = function() {
|
||||
this.displayPower = !this.displayPower;
|
||||
|
||||
if (this.displayPower) {
|
||||
Overlays.editOverlay(this.textOverlay, {
|
||||
leftMargin: 18,
|
||||
text: "2"
|
||||
});
|
||||
Overlays.editOverlay(this.powerOverlay, {
|
||||
text: this.power.toString(),
|
||||
visible: editToolsOn
|
||||
});
|
||||
} else {
|
||||
Overlays.editOverlay(this.textOverlay, {
|
||||
leftMargin: 13,
|
||||
text: this.scale.toString()
|
||||
});
|
||||
Overlays.editOverlay(this.powerOverlay, {
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.update = function() {
|
||||
if (this.displayPower) {
|
||||
Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()});
|
||||
} else {
|
||||
Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()});
|
||||
}
|
||||
}
|
||||
|
||||
this.incrementScale = function() {
|
||||
copyScale = false;
|
||||
if (this.power < MAX_VOXEL_SCALE_POWER) {
|
||||
++this.power;
|
||||
this.scale *= 2.0;
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
this.decrementScale = function() {
|
||||
copyScale = false;
|
||||
if (MIN_VOXEL_SCALE_POWER < this.power) {
|
||||
--this.power;
|
||||
this.scale /= 2.0;
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
this.clicked = function(x, y) {
|
||||
if (this.x < x && x < this.x + this.width &&
|
||||
this.y < y && y < this.y + this.height) {
|
||||
|
||||
if (x < this.x + this.FIRST_PART) {
|
||||
this.decrementScale();
|
||||
} else if (x < this.x + this.FIRST_PART + this.SECOND_PART) {
|
||||
this.switchDisplay();
|
||||
} else {
|
||||
this.incrementScale();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.cleanup = function() {
|
||||
Overlays.deleteOverlay(this.buttonsOverlay);
|
||||
Overlays.deleteOverlay(this.textOverlay);
|
||||
Overlays.deleteOverlay(this.powerOverlay);
|
||||
}
|
||||
|
||||
}
|
||||
var scaleSelector = new ScaleSelector();
|
||||
|
||||
function calculateVoxelFromIntersection(intersection, operation) {
|
||||
|
||||
var resultVoxel;
|
||||
|
||||
var x;
|
||||
var y;
|
||||
var z;
|
||||
|
||||
// if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest
|
||||
// ancestor voxel of our target size that contains our intersected voxel.
|
||||
if (voxelSize > intersection.voxel.s) {
|
||||
x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize;
|
||||
y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize;
|
||||
z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize;
|
||||
} else {
|
||||
// otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of.
|
||||
// if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result
|
||||
// in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting
|
||||
// voxel this still works and results in returning the intersecting voxel which is what we want
|
||||
var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5));
|
||||
|
||||
var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter);
|
||||
x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize;
|
||||
y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize;
|
||||
z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize;
|
||||
}
|
||||
resultVoxel = { x: x, y: y, z: z, s: voxelSize };
|
||||
var highlightAt = { x: x, y: y, z: z, s: voxelSize };
|
||||
|
||||
|
||||
|
||||
// we only do the "add to the face we're pointing at" adjustment, if the operation is an add
|
||||
// operation, and the target voxel size is equal to or smaller than the intersecting voxel.
|
||||
var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s));
|
||||
|
||||
// now we also want to calculate the "edge square" for the face for this voxel
|
||||
if (intersection.face == "MIN_X_FACE") {
|
||||
|
||||
highlightAt.x = x - zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.x -= voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
|
||||
} else if (intersection.face == "MAX_X_FACE") {
|
||||
|
||||
highlightAt.x = x + voxelSize + zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.x += resultVoxel.s;
|
||||
}
|
||||
|
||||
resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
|
||||
} else if (intersection.face == "MIN_Y_FACE") {
|
||||
|
||||
highlightAt.y = y - zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.y -= voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
|
||||
} else if (intersection.face == "MAX_Y_FACE") {
|
||||
|
||||
highlightAt.y = y + voxelSize + zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.y += voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust};
|
||||
resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust};
|
||||
resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust};
|
||||
|
||||
} else if (intersection.face == "MIN_Z_FACE") {
|
||||
|
||||
highlightAt.z = z - zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.z -= voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z};
|
||||
resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z};
|
||||
|
||||
} else if (intersection.face == "MAX_Z_FACE") {
|
||||
|
||||
highlightAt.z = z + voxelSize + zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.z += voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z};
|
||||
resultVoxel.topLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z};
|
||||
|
||||
}
|
||||
return resultVoxel;
|
||||
}
|
||||
|
||||
var trackLastMouseX = 0;
|
||||
var trackLastMouseY = 0;
|
||||
|
||||
function showPreviewLines() {
|
||||
|
||||
var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY);
|
||||
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
|
||||
if (intersection.intersects) {
|
||||
var resultVoxel = calculateVoxelFromIntersection(intersection, "");
|
||||
Overlays.editOverlay(linePreviewTop, { start: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true });
|
||||
Overlays.editOverlay(linePreviewBottom, { start: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true });
|
||||
Overlays.editOverlay(linePreviewLeft, { start: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true });
|
||||
Overlays.editOverlay(linePreviewRight, { start: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true });
|
||||
} else {
|
||||
Overlays.editOverlay(linePreviewTop, { visible: false });
|
||||
Overlays.editOverlay(linePreviewBottom, { visible: false });
|
||||
Overlays.editOverlay(linePreviewLeft, { visible: false });
|
||||
Overlays.editOverlay(linePreviewRight, { visible: false });
|
||||
}
|
||||
}
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
trackLastMouseX = event.x;
|
||||
trackLastMouseY = event.y;
|
||||
if (!voxelToolSelected) {
|
||||
return;
|
||||
}
|
||||
showPreviewLines();
|
||||
}
|
||||
|
||||
var BRUSH_RADIUS = 2;
|
||||
|
||||
function mousePressEvent(event) {
|
||||
var mouseX = event.x;
|
||||
var mouseY = event.y;
|
||||
|
||||
var clickedOnSomething = false;
|
||||
// Check if we clicked an overlay
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: mouseX, y: mouseY});
|
||||
|
||||
if (clickedOverlay == voxelTool) {
|
||||
voxelToolSelected = !voxelToolSelected;
|
||||
|
||||
if (voxelToolSelected == true) {
|
||||
Overlays.editOverlay(voxelTool, {
|
||||
color: activeUIColor
|
||||
});
|
||||
} else {
|
||||
Overlays.editOverlay(voxelTool, {
|
||||
color: UIColor
|
||||
});
|
||||
}
|
||||
|
||||
clickedOnSomething = true;
|
||||
} else if (scaleSelector.clicked(event.x, event.y)) {
|
||||
clickedOnSomething = true;
|
||||
voxelSize = scaleSelector.scale;
|
||||
}
|
||||
|
||||
// Return if we clicked on the UI or the voxel tool is disabled
|
||||
if (clickedOnSomething || !voxelToolSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute the picking ray for the click
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
var resultVoxel = calculateVoxelFromIntersection(intersection, "add");
|
||||
|
||||
|
||||
//Add a clump of sand voxels
|
||||
makeSphere(resultVoxel.x, resultVoxel.y, resultVoxel.z, voxelSize * BRUSH_RADIUS, voxelSize);
|
||||
}
|
||||
|
||||
var sandArray = [];
|
||||
var numSand = 0;
|
||||
|
||||
|
||||
//These arrays are used to buffer add/remove operations so they can be batched together
|
||||
var addArray = [];
|
||||
var addArraySize = 0;
|
||||
var removeArray = [];
|
||||
var removeArraySize = 0;
|
||||
|
||||
//The colors must be different
|
||||
var activeSandColor = { r: 234, g: 206, b: 106};
|
||||
var inactiveSandColor = { r: 233, g: 206, b: 106};
|
||||
|
||||
//This is used as an optimization, so that we
|
||||
//will check our 6 neighbors at most once.
|
||||
var adjacentVoxels = [];
|
||||
var numAdjacentVoxels = 0;
|
||||
//Stores a list of voxels we need to activate
|
||||
var activateMap = {};
|
||||
|
||||
var UPDATES_PER_SECOND = 12.0; // frames per second
|
||||
var frameIndex = 0.0;
|
||||
var oldFrameIndex = 0;
|
||||
|
||||
function update(deltaTime) {
|
||||
frameIndex += deltaTime * UPDATES_PER_SECOND;
|
||||
if (Math.floor(frameIndex) == oldFrameIndex) {
|
||||
return;
|
||||
}
|
||||
oldFrameIndex++;
|
||||
|
||||
//Clear the activate map each frame
|
||||
activateMap = {};
|
||||
|
||||
//Update all sand in our sandArray
|
||||
var i = 0;
|
||||
while (i < numSand) {
|
||||
//Update the sand voxel and if it doesn't move, deactivate it
|
||||
if (updateSand(i) == false) {
|
||||
deactivateSand(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < removeArraySize; i++) {
|
||||
var voxel = removeArray[i];
|
||||
Voxels.eraseVoxel(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
}
|
||||
removeArraySize = 0;
|
||||
|
||||
//Add all voxels that have moved
|
||||
for (var i = 0; i < addArraySize; i++) {
|
||||
var voxel = addArray[i];
|
||||
Voxels.setVoxel(voxel.x, voxel.y, voxel.z, voxel.s, voxel.r, voxel.g, voxel.b);
|
||||
}
|
||||
addArraySize = 0;
|
||||
|
||||
for (var key in activateMap) {
|
||||
var voxel = activateMap[key];
|
||||
Voxels.setVoxel(voxel.x, voxel.y, voxel.z, voxel.s, activeSandColor.r, activeSandColor.g, activeSandColor.b);
|
||||
sandArray[numSand++] = { x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b };
|
||||
}
|
||||
}
|
||||
|
||||
//Adds a sphere of sand at the center cx,cy,cz
|
||||
function makeSphere(cx, cy, cz, r, voxelSize) {
|
||||
|
||||
var r2 = r * r;
|
||||
var distance2;
|
||||
var dx;
|
||||
var dy;
|
||||
var dz;
|
||||
|
||||
for (var x = cx - r; x <= cx + r; x += voxelSize) {
|
||||
for (var y = cy - r; y <= cy + r; y += voxelSize) {
|
||||
for (var z = cz - r; z <= cz + r; z += voxelSize) {
|
||||
dx = Math.abs(x - cx);
|
||||
dy = Math.abs(y - cy);
|
||||
dz = Math.abs(z - cz);
|
||||
distance2 = dx * dx + dy * dy + dz * dz;
|
||||
if (distance2 <= r2 && isVoxelEmpty(x, y, z, voxelSize)) {
|
||||
Voxels.setVoxel(x, y, z, voxelSize, activeSandColor.r, activeSandColor.g, activeSandColor.b);
|
||||
sandArray[numSand++] = { x: x, y: y, z: z, s: voxelSize, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if a given voxel is empty
|
||||
function isVoxelEmpty(x, y, z, s, isAdjacent) {
|
||||
var halfSize = s / 2;
|
||||
var point = {x: x + halfSize, y: y + halfSize, z: z + halfSize };
|
||||
|
||||
var adjacent = Voxels.getVoxelEnclosingPointBlocking(point);
|
||||
//If color is all 0, we assume its air.
|
||||
|
||||
if (adjacent.red == 0 && adjacent.green == 0 && adjacent.blue == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isAdjacent) {
|
||||
adjacentVoxels[numAdjacentVoxels++] = adjacent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Moves voxel to x,y,z if the space is empty
|
||||
function tryMoveVoxel(voxel, x, y, z) {
|
||||
//If the adjacent voxel is empty, we will move to it.
|
||||
if (isVoxelEmpty(x, y, z, voxel.s, false)) {
|
||||
var hsize = voxel.s / 2;
|
||||
for (var i = 0; i < 5; i++) {
|
||||
var point = {x: voxel.x + directionVecs[i].x * voxel.s + hsize, y: voxel.y + directionVecs[i].y * voxel.s + hsize, z: voxel.z + directionVecs[i].z * voxel.s + hsize };
|
||||
adjacentVoxels[numAdjacentVoxels++] = Voxels.getVoxelEnclosingPointBlocking(point);
|
||||
}
|
||||
moveVoxel(voxel, x, y, z);
|
||||
|
||||
//Get all adjacent voxels for activation
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Moves voxel to x,y,z
|
||||
function moveVoxel(voxel, x, y, z) {
|
||||
activateNeighbors();
|
||||
removeArray[removeArraySize++] = {x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s};
|
||||
addArray[addArraySize++] = {x: x, y: y, z: z, s: voxel.s, r: activeSandColor.r, g: activeSandColor.g, b: activeSandColor.b};
|
||||
voxel.x = x;
|
||||
voxel.y = y;
|
||||
voxel.z = z;
|
||||
}
|
||||
|
||||
var LEFT = 0;
|
||||
var BACK = 1;
|
||||
var RIGHT = 2;
|
||||
var FRONT = 3;
|
||||
var TOP = 4;
|
||||
|
||||
//These indicate the different directions to neighbor voxels, so we can iterate them
|
||||
var directionVecs = [];
|
||||
directionVecs[LEFT] = {x: -1, y: 0, z: 0}; //Left
|
||||
directionVecs[BACK] = {x: 0, y: 0, z: -1}; //Back
|
||||
directionVecs[RIGHT] = {x: 1, y: 0, z: 0}; //Right
|
||||
directionVecs[FRONT] = {x: 0, y: 0, z: 1}; //Front
|
||||
directionVecs[TOP] = {x: 0, y: 1, z: 0}; //Top
|
||||
|
||||
function updateSand(i) {
|
||||
var voxel = sandArray[i];
|
||||
var size = voxel.s;
|
||||
var hsize = size / 2;
|
||||
numAdjacentVoxels = 0;
|
||||
|
||||
//Down
|
||||
if (tryMoveVoxel(voxel, voxel.x, voxel.y - size, voxel.z)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Left, back, right, front
|
||||
for (var i = 0; i < 4; i++) {
|
||||
if (isVoxelEmpty(voxel.x + directionVecs[i].x * size, voxel.y + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size, size, true)
|
||||
&& isVoxelEmpty(voxel.x + directionVecs[i].x * size, (voxel.y - size) + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size, size, false)) {
|
||||
//get the rest of the adjacent voxels
|
||||
for (var j = i + 1; j < 5; j++) {
|
||||
var point = {x: voxel.x + directionVecs[j].x * size + hsize, y: voxel.y + directionVecs[j].y * size + hsize, z: voxel.z + directionVecs[j].z * size + hsize };
|
||||
adjacentVoxels[numAdjacentVoxels++] = Voxels.getVoxelEnclosingPointBlocking(point);
|
||||
}
|
||||
moveVoxel(voxel, voxel.x + directionVecs[i].x * size, voxel.y + directionVecs[i].y * size, voxel.z + directionVecs[i].z * size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function activateNeighbors() {
|
||||
for (var i = 0; i < numAdjacentVoxels; i++) {
|
||||
var voxel = adjacentVoxels[i];
|
||||
//Check if this neighbor is inactive, if so, activate it
|
||||
if (voxel.red == inactiveSandColor.r && voxel.green == inactiveSandColor.g && voxel.blue == inactiveSandColor.b) {
|
||||
activateMap[voxel.x.toString() + "," + voxel.y.toString() + ',' + voxel.z.toString()] = voxel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Deactivates a sand voxel to save processing power
|
||||
function deactivateSand(i) {
|
||||
var voxel = sandArray[i];
|
||||
addArray[addArraySize++] = {x: voxel.x, y: voxel.y, z: voxel.z, s: voxel.s, r: inactiveSandColor.r, g: inactiveSandColor.g, b: inactiveSandColor.b};
|
||||
sandArray[i] = sandArray[numSand-1];
|
||||
numSand--;
|
||||
}
|
||||
|
||||
//Cleanup
|
||||
function scriptEnding() {
|
||||
for (var i = 0; i < numSand; i++) {
|
||||
var voxel = sandArray[i];
|
||||
Voxels.eraseVoxel(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
}
|
||||
Overlays.deleteOverlay(linePreviewTop);
|
||||
Overlays.deleteOverlay(linePreviewBottom);
|
||||
Overlays.deleteOverlay(linePreviewLeft);
|
||||
Overlays.deleteOverlay(linePreviewRight);
|
||||
scaleSelector.cleanup();
|
||||
Overlays.deleteOverlay(voxelTool);
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
|
||||
Script.update.connect(update);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
Voxels.setMaxPacketSize(1); //this is needed or a bug occurs :(
|
||||
Voxels.setPacketsPerSecond(10000);
|
|
@ -46,7 +46,7 @@ function vInterpolate(a, b, fraction) {
|
|||
}
|
||||
|
||||
var position = { x: 5.0, y: 0.6, z: 5.0 };
|
||||
Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255);
|
||||
//Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255);
|
||||
|
||||
var totalEntities = 0;
|
||||
function makeFountain(deltaTime) {
|
||||
|
|
|
@ -208,7 +208,7 @@ function checkControllerSide(hand) {
|
|||
gravity: { x: 0, y: 0, z: 0},
|
||||
inHand: true,
|
||||
dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS },
|
||||
damping: 0.999,
|
||||
damping: 0.00001,
|
||||
modelURL: modelUrl,
|
||||
modelScale: FRISBEE_MODEL_SCALE,
|
||||
modelRotation: hand.holdRotation(),
|
||||
|
@ -235,7 +235,7 @@ function checkControllerSide(hand) {
|
|||
gravity: { x: 0, y: 0, z: 0},
|
||||
inHand: true,
|
||||
dimensions: { x: FRISBEE_RADIUS, y: FRISBEE_RADIUS / 5, z: FRISBEE_RADIUS },
|
||||
damping: 0.999,
|
||||
damping: 0.00001,
|
||||
modelURL: frisbeeURL(),
|
||||
modelScale: FRISBEE_MODEL_SCALE,
|
||||
modelRotation: hand.holdRotation(),
|
||||
|
@ -444,4 +444,4 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
|||
Menu.menuItemEvent.connect(menuItemEvent);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
Script.update.connect(checkController);
|
||||
Script.update.connect(controlFrisbees);
|
||||
Script.update.connect(controlFrisbees);
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
//
|
||||
// gameoflife.js
|
||||
// examples
|
||||
//
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// The following is an example of Conway's Game of Life (http://en.wikipedia.org/wiki/Conway's_Game_of_Life)
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var NUMBER_OF_CELLS_EACH_DIMENSION = 64;
|
||||
var NUMBER_OF_CELLS = NUMBER_OF_CELLS_EACH_DIMENSION * NUMBER_OF_CELLS_EACH_DIMENSION;
|
||||
|
||||
var currentCells = [];
|
||||
var nextCells = [];
|
||||
|
||||
var METER_LENGTH = 1;
|
||||
var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION;
|
||||
|
||||
// randomly populate the cell start values
|
||||
for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
// create the array to hold this row
|
||||
currentCells[i] = [];
|
||||
|
||||
// create the array to hold this row in the nextCells array
|
||||
nextCells[i] = [];
|
||||
|
||||
for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
currentCells[i][j] = Math.floor(Math.random() * 2);
|
||||
|
||||
// put the same value in the nextCells array for first board draw
|
||||
nextCells[i][j] = currentCells[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
function isNeighbourAlive(i, j) {
|
||||
if (i < 0 || i >= NUMBER_OF_CELLS_EACH_DIMENSION
|
||||
|| i < 0 || j >= NUMBER_OF_CELLS_EACH_DIMENSION) {
|
||||
return 0;
|
||||
} else {
|
||||
return currentCells[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
function updateCells() {
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
// figure out the number of live neighbours for the i-j cell
|
||||
var liveNeighbours =
|
||||
isNeighbourAlive(i + 1, j - 1) + isNeighbourAlive(i + 1, j) + isNeighbourAlive(i + 1, j + 1) +
|
||||
isNeighbourAlive(i, j - 1) + isNeighbourAlive(i, j + 1) +
|
||||
isNeighbourAlive(i - 1, j - 1) + isNeighbourAlive(i - 1, j) + isNeighbourAlive(i - 1, j + 1);
|
||||
|
||||
if (currentCells[i][j]) {
|
||||
// live cell
|
||||
|
||||
if (liveNeighbours < 2) {
|
||||
// rule #1 - under-population - this cell will die
|
||||
// mark it zero to mark the change
|
||||
nextCells[i][j] = 0;
|
||||
} else if (liveNeighbours < 4) {
|
||||
// rule #2 - this cell lives
|
||||
// mark it -1 to mark no change
|
||||
nextCells[i][j] = -1;
|
||||
} else {
|
||||
// rule #3 - overcrowding - this cell dies
|
||||
// mark it zero to mark the change
|
||||
nextCells[i][j] = 0;
|
||||
}
|
||||
} else {
|
||||
// dead cell
|
||||
if (liveNeighbours == 3) {
|
||||
// rule #4 - reproduction - this cell revives
|
||||
// mark it one to mark the change
|
||||
nextCells[i][j] = 1;
|
||||
} else {
|
||||
// this cell stays dead
|
||||
// mark it -1 for no change
|
||||
nextCells[i][j] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.random() < 0.001) {
|
||||
// Random mutation to keep things interesting in there.
|
||||
nextCells[i][j] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
for (j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
if (nextCells[i][j] != -1) {
|
||||
// there has been a change to this cell, change the value in the currentCells array
|
||||
currentCells[i][j] = nextCells[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendNextCells() {
|
||||
for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) {
|
||||
for (var j = 0; j < NUMBER_OF_CELLS_EACH_DIMENSION; j++) {
|
||||
if (nextCells[i][j] != -1) {
|
||||
// there has been a change to the state of this cell, send it
|
||||
|
||||
// find the x and y position for this voxel, z = 0
|
||||
var x = j * cellScale;
|
||||
var y = i * cellScale;
|
||||
|
||||
// queue a packet to add a voxel for the new cell
|
||||
var color = (nextCells[i][j] == 1) ? 255 : 1;
|
||||
Voxels.setVoxel(x, y, 0, cellScale, color, color, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sentFirstBoard = false;
|
||||
|
||||
function step(deltaTime) {
|
||||
if (sentFirstBoard) {
|
||||
// we've already sent the first full board, perform a step in time
|
||||
updateCells();
|
||||
} else {
|
||||
// this will be our first board send
|
||||
sentFirstBoard = true;
|
||||
}
|
||||
|
||||
sendNextCells();
|
||||
}
|
||||
|
||||
print("here");
|
||||
Script.update.connect(step);
|
||||
Voxels.setPacketsPerSecond(200);
|
||||
print("now here");
|
|
@ -116,7 +116,7 @@ function updateWarp() {
|
|||
direction: { x: 0, y: -1, z: 0 }
|
||||
};
|
||||
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
var intersection = Entities.findRayIntersection(pickRay);
|
||||
|
||||
if (intersection.intersects && intersection.distance < WARP_PICK_MAX_DISTANCE) {
|
||||
// Warp 1 meter above the object - this is an approximation
|
||||
|
|
|
@ -145,7 +145,7 @@ function shootTarget() {
|
|||
velocity: velocity,
|
||||
gravity: { x: 0, y: TARGET_GRAVITY, z: 0 },
|
||||
lifetime: 1000.0,
|
||||
damping: 0.99 });
|
||||
damping: 0.0001 });
|
||||
|
||||
// Record start time
|
||||
shotTime = new Date();
|
||||
|
@ -155,45 +155,6 @@ function shootTarget() {
|
|||
Audio.playSound(targetLaunchSound, audioOptions);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function entityCollisionWithVoxel(entity, voxel, collision) {
|
||||
|
||||
print("entityCollisionWithVoxel....");
|
||||
|
||||
var VOXEL_SIZE = 0.5;
|
||||
// Don't make this big. I mean it.
|
||||
var CRATER_RADIUS = 5;
|
||||
var entityProperties = Entities.getEntityProperties(entity);
|
||||
var position = entityProperties.position;
|
||||
Entities.deleteEntity(entity);
|
||||
|
||||
audioOptions.position = collision.contactPoint;
|
||||
Audio.playSound(impactSound, audioOptions);
|
||||
|
||||
// Make a crater
|
||||
var center = collision.contactPoint;
|
||||
var RADIUS = CRATER_RADIUS * VOXEL_SIZE;
|
||||
var RADIUS2 = RADIUS * RADIUS;
|
||||
var distance2;
|
||||
var dx;
|
||||
var dy;
|
||||
var dz;
|
||||
for (var x = center.x - RADIUS; x <= center.x + RADIUS; x += VOXEL_SIZE) {
|
||||
for (var y = center.y - RADIUS; y <= center.y + RADIUS; y += VOXEL_SIZE) {
|
||||
for (var z = center.z - RADIUS; z <= center.z + RADIUS; z += VOXEL_SIZE) {
|
||||
dx = Math.abs(x - center.x);
|
||||
dy = Math.abs(y - center.y);
|
||||
dz = Math.abs(z - center.z);
|
||||
distance2 = dx * dx + dy * dy + dz * dz;
|
||||
if (distance2 <= RADIUS2) {
|
||||
Voxels.eraseVoxel(x, y, z, VOXEL_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function entityCollisionWithEntity(entity1, entity2, collision) {
|
||||
score++;
|
||||
if (showScore) {
|
||||
|
@ -355,7 +316,6 @@ function scriptEnding() {
|
|||
MyAvatar.detachOne(gunModel);
|
||||
}
|
||||
|
||||
Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel);
|
||||
Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
Script.update.connect(update);
|
||||
|
|
|
@ -1,834 +0,0 @@
|
|||
//
|
||||
// growPlants.js
|
||||
// examples
|
||||
//
|
||||
// Created by Benjamin Arnold on May 29, 2014
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This sample script allows the user to grow different types of plants on the voxels
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("libraries/globals.js");
|
||||
|
||||
var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting
|
||||
var previewLineWidth = 2.0;
|
||||
|
||||
var voxelSize = 1;
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||
|
||||
var MAX_VOXEL_SCALE_POWER = 5;
|
||||
var MIN_VOXEL_SCALE_POWER = -8;
|
||||
var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER);
|
||||
var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER);
|
||||
|
||||
|
||||
var linePreviewTop = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 255, blue: 0},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
var linePreviewBottom = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 255, blue: 0},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
var linePreviewLeft = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 255, blue: 0},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
var linePreviewRight = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0},
|
||||
end: { x: 0, y: 0, z: 0},
|
||||
color: { red: 0, green: 255, blue: 0},
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: previewLineWidth
|
||||
});
|
||||
|
||||
|
||||
var UIColor = { red: 0, green: 160, blue: 0};
|
||||
var activeUIColor = { red: 0, green: 255, blue: 0};
|
||||
|
||||
var toolHeight = 50;
|
||||
var toolWidth = 50;
|
||||
|
||||
var editToolsOn = true;
|
||||
|
||||
var voxelToolSelected = false;
|
||||
|
||||
var scaleSelectorWidth = 144;
|
||||
var scaleSelectorHeight = 37;
|
||||
|
||||
var scaleSelectorX = windowDimensions.x / 5.0;
|
||||
var scaleSelectorY = windowDimensions.y - scaleSelectorHeight;
|
||||
|
||||
var voxelTool = Overlays.addOverlay("image", {
|
||||
x: scaleSelectorX + scaleSelectorWidth + 1, y: windowDimensions.y - toolHeight, width: toolWidth, height: toolHeight,
|
||||
subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight },
|
||||
imageURL: toolIconUrl + "voxel-tool.svg",
|
||||
visible: editToolsOn,
|
||||
color: UIColor,
|
||||
alpha: 0.9
|
||||
});
|
||||
|
||||
var copyScale = true;
|
||||
function ScaleSelector() {
|
||||
this.x = scaleSelectorX;
|
||||
this.y = scaleSelectorY;
|
||||
this.width = scaleSelectorWidth;
|
||||
this.height = scaleSelectorHeight;
|
||||
|
||||
this.displayPower = false;
|
||||
this.scale = 1.0;
|
||||
this.power = 0;
|
||||
|
||||
this.FIRST_PART = this.width * 40.0 / 100.0;
|
||||
this.SECOND_PART = this.width * 37.0 / 100.0;
|
||||
|
||||
this.buttonsOverlay = Overlays.addOverlay("image", {
|
||||
x: this.x, y: this.y,
|
||||
width: this.width, height: this.height,
|
||||
//subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight },
|
||||
imageURL: toolIconUrl + "voxel-size-selector.svg",
|
||||
alpha: 0.9,
|
||||
visible: editToolsOn,
|
||||
color: activeUIColor
|
||||
});
|
||||
this.textOverlay = Overlays.addOverlay("text", {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
width: this.SECOND_PART, height: this.height,
|
||||
topMargin: 13,
|
||||
text: this.scale.toString(),
|
||||
backgroundAlpha: 0.0,
|
||||
visible: editToolsOn,
|
||||
color: activeUIColor
|
||||
});
|
||||
this.powerOverlay = Overlays.addOverlay("text", {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
width: this.SECOND_PART, height: this.height,
|
||||
leftMargin: 28,
|
||||
text: this.power.toString(),
|
||||
backgroundAlpha: 0.0,
|
||||
visible: false,
|
||||
color: activeUIColor
|
||||
});
|
||||
this.setScale = function(scale) {
|
||||
if (scale > MAX_VOXEL_SCALE) {
|
||||
scale = MAX_VOXEL_SCALE;
|
||||
}
|
||||
if (scale < MIN_VOXEL_SCALE) {
|
||||
scale = MIN_VOXEL_SCALE;
|
||||
}
|
||||
|
||||
this.scale = scale;
|
||||
this.power = Math.floor(Math.log(scale) / Math.log(2));
|
||||
this.update();
|
||||
}
|
||||
|
||||
this.show = function(doShow) {
|
||||
Overlays.editOverlay(this.buttonsOverlay, {visible: doShow});
|
||||
Overlays.editOverlay(this.textOverlay, {visible: doShow});
|
||||
Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower});
|
||||
}
|
||||
|
||||
this.move = function() {
|
||||
this.x = swatchesX + swatchesWidth;
|
||||
this.y = swatchesY;
|
||||
|
||||
Overlays.editOverlay(this.buttonsOverlay, {
|
||||
x: this.x, y: this.y,
|
||||
});
|
||||
Overlays.editOverlay(this.textOverlay, {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
});
|
||||
Overlays.editOverlay(this.powerOverlay, {
|
||||
x: this.x + this.FIRST_PART, y: this.y,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.switchDisplay = function() {
|
||||
this.displayPower = !this.displayPower;
|
||||
|
||||
if (this.displayPower) {
|
||||
Overlays.editOverlay(this.textOverlay, {
|
||||
leftMargin: 18,
|
||||
text: "2"
|
||||
});
|
||||
Overlays.editOverlay(this.powerOverlay, {
|
||||
text: this.power.toString(),
|
||||
visible: editToolsOn
|
||||
});
|
||||
} else {
|
||||
Overlays.editOverlay(this.textOverlay, {
|
||||
leftMargin: 13,
|
||||
text: this.scale.toString()
|
||||
});
|
||||
Overlays.editOverlay(this.powerOverlay, {
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.update = function() {
|
||||
if (this.displayPower) {
|
||||
Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()});
|
||||
} else {
|
||||
Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()});
|
||||
}
|
||||
}
|
||||
|
||||
this.incrementScale = function() {
|
||||
copyScale = false;
|
||||
if (this.power < MAX_VOXEL_SCALE_POWER) {
|
||||
++this.power;
|
||||
this.scale *= 2.0;
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
this.decrementScale = function() {
|
||||
copyScale = false;
|
||||
if (MIN_VOXEL_SCALE_POWER < this.power) {
|
||||
--this.power;
|
||||
this.scale /= 2.0;
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
this.clicked = function(x, y) {
|
||||
if (this.x < x && x < this.x + this.width &&
|
||||
this.y < y && y < this.y + this.height) {
|
||||
|
||||
if (x < this.x + this.FIRST_PART) {
|
||||
this.decrementScale();
|
||||
} else if (x < this.x + this.FIRST_PART + this.SECOND_PART) {
|
||||
this.switchDisplay();
|
||||
} else {
|
||||
this.incrementScale();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.cleanup = function() {
|
||||
Overlays.deleteOverlay(this.buttonsOverlay);
|
||||
Overlays.deleteOverlay(this.textOverlay);
|
||||
Overlays.deleteOverlay(this.powerOverlay);
|
||||
}
|
||||
|
||||
}
|
||||
var scaleSelector = new ScaleSelector();
|
||||
|
||||
|
||||
function calculateVoxelFromIntersection(intersection, operation) {
|
||||
|
||||
var resultVoxel;
|
||||
|
||||
var x;
|
||||
var y;
|
||||
var z;
|
||||
|
||||
// if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest
|
||||
// ancestor voxel of our target size that contains our intersected voxel.
|
||||
if (voxelSize > intersection.voxel.s) {
|
||||
x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize;
|
||||
y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize;
|
||||
z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize;
|
||||
} else {
|
||||
// otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of.
|
||||
// if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result
|
||||
// in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting
|
||||
// voxel this still works and results in returning the intersecting voxel which is what we want
|
||||
var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5));
|
||||
|
||||
var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter);
|
||||
x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize;
|
||||
y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize;
|
||||
z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize;
|
||||
}
|
||||
resultVoxel = { x: x, y: y, z: z, s: voxelSize };
|
||||
var highlightAt = { x: x, y: y, z: z, s: voxelSize };
|
||||
|
||||
|
||||
|
||||
// we only do the "add to the face we're pointing at" adjustment, if the operation is an add
|
||||
// operation, and the target voxel size is equal to or smaller than the intersecting voxel.
|
||||
var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s));
|
||||
|
||||
// now we also want to calculate the "edge square" for the face for this voxel
|
||||
if (intersection.face == "MIN_X_FACE") {
|
||||
|
||||
highlightAt.x = x - zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.x -= voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
|
||||
} else if (intersection.face == "MAX_X_FACE") {
|
||||
|
||||
highlightAt.x = x + voxelSize + zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.x += resultVoxel.s;
|
||||
}
|
||||
|
||||
resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
|
||||
} else if (intersection.face == "MIN_Y_FACE") {
|
||||
|
||||
highlightAt.y = y - zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.y -= voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust };
|
||||
|
||||
} else if (intersection.face == "MAX_Y_FACE") {
|
||||
|
||||
highlightAt.y = y + voxelSize + zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.y += voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust};
|
||||
resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust};
|
||||
resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust};
|
||||
|
||||
} else if (intersection.face == "MIN_Z_FACE") {
|
||||
|
||||
highlightAt.z = z - zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.z -= voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z};
|
||||
resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z};
|
||||
|
||||
} else if (intersection.face == "MAX_Z_FACE") {
|
||||
|
||||
highlightAt.z = z + voxelSize + zFightingSizeAdjust;
|
||||
if (wantAddAdjust) {
|
||||
resultVoxel.z += voxelSize;
|
||||
}
|
||||
|
||||
resultVoxel.bottomLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.bottomRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z};
|
||||
resultVoxel.topLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z };
|
||||
resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z};
|
||||
|
||||
}
|
||||
return resultVoxel;
|
||||
}
|
||||
|
||||
var trackLastMouseX = 0;
|
||||
var trackLastMouseY = 0;
|
||||
|
||||
function showPreviewLines() {
|
||||
|
||||
var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY);
|
||||
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
|
||||
if (intersection.intersects) {
|
||||
var resultVoxel = calculateVoxelFromIntersection(intersection, "");
|
||||
Overlays.editOverlay(linePreviewTop, { start: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true });
|
||||
Overlays.editOverlay(linePreviewBottom, { start: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true });
|
||||
Overlays.editOverlay(linePreviewLeft, { start: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true });
|
||||
Overlays.editOverlay(linePreviewRight, { start: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true });
|
||||
} else {
|
||||
Overlays.editOverlay(linePreviewTop, { visible: false });
|
||||
Overlays.editOverlay(linePreviewBottom, { visible: false });
|
||||
Overlays.editOverlay(linePreviewLeft, { visible: false });
|
||||
Overlays.editOverlay(linePreviewRight, { visible: false });
|
||||
}
|
||||
}
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
trackLastMouseX = event.x;
|
||||
trackLastMouseY = event.y;
|
||||
if (!voxelToolSelected) {
|
||||
return;
|
||||
}
|
||||
showPreviewLines();
|
||||
}
|
||||
|
||||
|
||||
// Array of possible trees, right now there is only one
|
||||
var treeTypes = [];
|
||||
|
||||
treeTypes.push({
|
||||
name: "Tall Green",
|
||||
// Voxel Colors
|
||||
wood: { r: 133, g: 81, b: 53 },
|
||||
leaves: { r: 22, g: 83, b: 31 },
|
||||
|
||||
// How tall the tree is
|
||||
height: { min: 20, max: 60 },
|
||||
middleHeight: 0.3,
|
||||
|
||||
// Chance of making a branch
|
||||
branchChance: { min: 0.01, max: 0.1 },
|
||||
branchLength: { min: 30, max: 60 },
|
||||
branchThickness: { min: 2, max: 7},
|
||||
|
||||
// The width of the core, affects width and shape
|
||||
coreWidth: { min: 1, max: 4 },
|
||||
|
||||
//TODO: Make this quadratic splines instead of linear
|
||||
bottomThickness: { min: 2, max: 8 },
|
||||
middleThickness: { min: 1, max: 4 },
|
||||
topThickness: { min: 3, max: 6 },
|
||||
|
||||
//Modifies leaves at top
|
||||
leafCapSizeOffset: 0
|
||||
});
|
||||
|
||||
// Applies noise to color
|
||||
var colorNoiseRange = 0.2;
|
||||
|
||||
|
||||
// Useful constants
|
||||
var LEFT = 0;
|
||||
var BACK = 1;
|
||||
var RIGHT = 2;
|
||||
var FRONT = 3;
|
||||
var UP = 4;
|
||||
|
||||
// Interpolates between min and max of treevar based on b
|
||||
function interpolate(treeVar, b) {
|
||||
return (treeVar.min + (treeVar.max - treeVar.min) * b);
|
||||
}
|
||||
|
||||
function makeBranch(x, y, z, step, length, dir, thickness, wood, leaves) {
|
||||
var moveDir;
|
||||
|
||||
var currentThickness;
|
||||
//thickness attenuates to thickness - 3
|
||||
var finalThickness = thickness - 3;
|
||||
if (finalThickness < 1) {
|
||||
finalThickness = 1;
|
||||
}
|
||||
//Iterative branch generation
|
||||
while (true) {
|
||||
|
||||
//If we are at the end, place a ball of leaves
|
||||
if (step == 0) {
|
||||
makeSphere(x, y, z, 2 + finalThickness, leaves);
|
||||
return;
|
||||
}
|
||||
//thickness attenuation
|
||||
currentThickness = Math.round((finalThickness + (thickness - finalThickness) * (step/length))) - 1;
|
||||
|
||||
|
||||
// If the branch is thick, grow a vertical slice
|
||||
if (currentThickness > 0) {
|
||||
for (var i = -currentThickness; i <= currentThickness; i++) {
|
||||
var len = currentThickness - Math.abs(i);
|
||||
switch (dir) {
|
||||
case 0: //left
|
||||
case 2: //right
|
||||
growInDirection(x, y + i * voxelSize, z, len, len, BACK, wood, false, true);
|
||||
growInDirection(x, y + i * voxelSize, z, len, len, FRONT, wood, false, false)
|
||||
break;
|
||||
case 1: //back
|
||||
case 3: //front
|
||||
growInDirection(x, y + i * voxelSize, z, len, len, LEFT, wood, false, true);
|
||||
growInDirection(x, y + i * voxelSize, z, len, len, RIGHT, wood, false, false)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Otherwise place a single voxel
|
||||
var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0;
|
||||
Voxels.setVoxel(x, y, z, voxelSize, wood.r * colorNoise, wood.g * colorNoise, wood.b * colorNoise);
|
||||
}
|
||||
|
||||
// determines random change in direction for branch
|
||||
var r = Math.floor(Math.random() * 9);
|
||||
|
||||
|
||||
if (r >= 6){
|
||||
moveDir = dir; //in same direction
|
||||
} else if (r >= 4) {
|
||||
moveDir = UP; //up
|
||||
}
|
||||
else if (dir == LEFT){
|
||||
if (r >= 2){
|
||||
moveDir = FRONT;
|
||||
}
|
||||
else{
|
||||
moveDir = BACK;
|
||||
}
|
||||
}
|
||||
else if (dir == BACK){
|
||||
if (r >= 2){
|
||||
moveDir = LEFT;
|
||||
}
|
||||
else{
|
||||
moveDir = RIGHT;
|
||||
}
|
||||
}
|
||||
else if (dir == RIGHT){
|
||||
if (r >= 2){
|
||||
moveDir = BACK;
|
||||
}
|
||||
else{
|
||||
moveDir = FRONT;
|
||||
}
|
||||
}
|
||||
else if (dir == FRONT){
|
||||
if (r >= 2){
|
||||
moveDir = RIGHT;
|
||||
}
|
||||
else{
|
||||
moveDir = LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
//Move the branch by moveDir
|
||||
switch (moveDir) {
|
||||
case 0: //left
|
||||
x = x - voxelSize;
|
||||
break;
|
||||
case 1: //back
|
||||
z = z - voxelSize;
|
||||
break;
|
||||
case 2: //right
|
||||
x = x + voxelSize;
|
||||
break;
|
||||
case 3: //front
|
||||
z = z + voxelSize;
|
||||
break;
|
||||
case 4: //up
|
||||
y = y + voxelSize;
|
||||
break;
|
||||
}
|
||||
|
||||
step--;
|
||||
}
|
||||
}
|
||||
|
||||
// Places a sphere of voxels
|
||||
function makeSphere(x, y, z, radius, color) {
|
||||
if (radius <= 0) {
|
||||
return;
|
||||
}
|
||||
var width = radius * 2 + 1;
|
||||
var distance;
|
||||
|
||||
for (var i = -radius; i <= radius; i++){
|
||||
for (var j = -radius; j <= radius; j++){
|
||||
for (var k = -radius; k <= radius; k++){
|
||||
distance = Math.sqrt(i * i + j * j + k * k);
|
||||
if (distance <= radius){
|
||||
var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0;
|
||||
Voxels.setVoxel(x + i * voxelSize, y + j * voxelSize, z + k * voxelSize, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function growInDirection(x, y, z, step, length, dir, color, isSideBranching, addVoxel) {
|
||||
|
||||
|
||||
if (addVoxel == true) {
|
||||
var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0;
|
||||
Voxels.setVoxel(x, y, z, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise);
|
||||
}
|
||||
|
||||
// If this is a main vein, it will branch outward perpendicular to its motion
|
||||
if (isSideBranching == true){
|
||||
var step2;
|
||||
if (step >= length - 1){
|
||||
step2 = length;
|
||||
}
|
||||
else{
|
||||
step2 = step + 1;
|
||||
}
|
||||
growInDirection(x, y, z, step, length, BACK, color, false, false);
|
||||
growInDirection(x, y, z, step, length, FRONT, color, false, false);
|
||||
}
|
||||
|
||||
if (step < 1) return;
|
||||
|
||||
// Recursively move in the direction
|
||||
if (dir == LEFT) { //left
|
||||
growInDirection(x - voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true);
|
||||
}
|
||||
else if (dir == BACK) { //back
|
||||
growInDirection(x, y, z - voxelSize, step - 1, length, dir, color, isSideBranching, true);
|
||||
}
|
||||
else if (dir == RIGHT) { //right
|
||||
growInDirection(x + voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true);
|
||||
}
|
||||
else if (dir == FRONT) {//front
|
||||
growInDirection(x, y, z + voxelSize, step - 1, length, dir, color, isSideBranching, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Grows the thickness of the tree
|
||||
function growHorizontalSlice(x, y, z, thickness, color, side) {
|
||||
// The side variable determines which directions we should grow in
|
||||
// it is an optimization that prevents us from visiting voxels multiple
|
||||
// times for trees with a coreWidth > 1
|
||||
|
||||
// side:
|
||||
// 8 == all directions
|
||||
// 0 1 2
|
||||
// 3 -1 4
|
||||
// 5 6 7
|
||||
|
||||
Voxels.setVoxel(x, y, z, voxelSize, color.r, color.g, color.b);
|
||||
|
||||
//We are done if there is no thickness
|
||||
if (thickness == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (side) {
|
||||
case 0:
|
||||
growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false);
|
||||
break;
|
||||
case 1:
|
||||
growInDirection(x, y, z, thickness, thickness, BACK, color, false, false);
|
||||
break;
|
||||
case 2:
|
||||
growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false);
|
||||
break;
|
||||
case 3:
|
||||
growInDirection(x, y, z, thickness, thickness, LEFT, color, false, false);
|
||||
break;
|
||||
case 4:
|
||||
growInDirection(x, y, z, thickness, thickness, BACK, color, false, false);
|
||||
break;
|
||||
case 5:
|
||||
growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false);
|
||||
break;
|
||||
case 6:
|
||||
growInDirection(x, y, z, thickness, thickness, FRONT, color, false, false);
|
||||
break;
|
||||
case 7:
|
||||
growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false);
|
||||
break;
|
||||
case 8:
|
||||
if (thickness > 1){
|
||||
growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false);
|
||||
growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false)
|
||||
} else if (thickness == 1){
|
||||
Voxels.setVoxel(x - voxelSize, y, z, voxelSize, color.r, color.g, color.b);
|
||||
Voxels.setVoxel(x + voxelSize, y, z, voxelSize, color.r, color.g, color.b);
|
||||
Voxels.setVoxel(x, y, z - voxelSize, voxelSize, color.r, color.g, color.b);
|
||||
Voxels.setVoxel(x, y, z + voxelSize, voxelSize, color.r, color.g, color.b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function computeSide(x, z, coreWidth) {
|
||||
// side:
|
||||
// 8 == all directions
|
||||
// 0 1 2
|
||||
// 3 -1 4
|
||||
// 5 6 7
|
||||
|
||||
// if the core is only a single block, we can grow out in all directions
|
||||
if (coreWidth == 1){
|
||||
return 8;
|
||||
}
|
||||
|
||||
// Back face
|
||||
if (z == 0) {
|
||||
if (x == 0) {
|
||||
return 0;
|
||||
} else if (x == coreWidth - 1) {
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Front face
|
||||
if (z == (coreWidth - 1)) {
|
||||
if (x == 0) {
|
||||
return 5;
|
||||
} else if (x == (coreWidth - 1)) {
|
||||
return 7;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
// Left face
|
||||
if (x == 0) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Right face
|
||||
if (x == (coreWidth - 1)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
//Interior
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
function growTree(x, y, z, tree) {
|
||||
|
||||
// The size of the tree, from 0-1
|
||||
var treeSize = Math.random();
|
||||
|
||||
// Get tree properties by interpolating with the treeSize
|
||||
var height = interpolate(tree.height, treeSize);
|
||||
var baseHeight = Math.ceil(tree.middleHeight * height);
|
||||
var bottomThickness = interpolate(tree.bottomThickness, treeSize);
|
||||
var middleThickness = interpolate(tree.middleThickness, treeSize);
|
||||
var topThickness = interpolate(tree.topThickness, treeSize);
|
||||
var coreWidth = Math.ceil(interpolate(tree.coreWidth, treeSize));
|
||||
|
||||
var thickness;
|
||||
var side;
|
||||
|
||||
//Loop upwards through each slice of the tree
|
||||
for (var i = 0; i < height; i++){
|
||||
|
||||
//Branch properties are based on current height as well as the overall tree size
|
||||
var branchChance = interpolate(tree.branchChance, i / height);
|
||||
var branchLength = Math.ceil(interpolate(tree.branchLength, (i / height) * treeSize));
|
||||
var branchThickness = Math.round(interpolate(tree.branchThickness, (i / height) * treeSize));
|
||||
|
||||
// Get the "thickness" of the tree by doing linear interpolation between the middle thickness
|
||||
// and the top and bottom thickness.
|
||||
if (i <= baseHeight && baseHeight != 0){
|
||||
thickness = (i / (baseHeight) * (middleThickness - bottomThickness) + bottomThickness);
|
||||
} else {
|
||||
var denom = ((height - baseHeight)) * (topThickness - middleThickness) + middleThickness;
|
||||
if (denom != 0) {
|
||||
thickness = (i - baseHeight) / denom;
|
||||
} else {
|
||||
thickness = 0;
|
||||
}
|
||||
}
|
||||
// The core of the tree is a vertical rectangular prism through the middle of the tree
|
||||
|
||||
//Loop through the "core", which helps shape the trunk
|
||||
var startX = x - Math.floor(coreWidth / 2) * voxelSize;
|
||||
var startZ = z - Math.floor(coreWidth / 2) * voxelSize;
|
||||
for (var j = 0; j < coreWidth; j++) {
|
||||
for (var k = 0; k < coreWidth; k++) {
|
||||
//determine which side of the tree we are on
|
||||
side = computeSide(j, k, coreWidth);
|
||||
//grow a horizontal slice of the tree
|
||||
growHorizontalSlice(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, Math.floor(thickness), tree.wood, side);
|
||||
|
||||
// Branches
|
||||
if (side != -1) {
|
||||
var r = Math.random();
|
||||
if (r <= branchChance){
|
||||
var dir = Math.floor((Math.random() * 4));
|
||||
makeBranch(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, branchLength, branchLength, dir, branchThickness, tree.wood, tree.leaves);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
makeSphere(x, y + height * voxelSize, z, topThickness + coreWidth + tree.leafCapSizeOffset, tree.leaves);
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
var mouseX = event.x;
|
||||
var mouseY = event.y;
|
||||
|
||||
var clickedOnSomething = false;
|
||||
// Check if we clicked an overlay
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: mouseX, y: mouseY});
|
||||
|
||||
if (clickedOverlay == voxelTool) {
|
||||
voxelToolSelected = !voxelToolSelected;
|
||||
|
||||
if (voxelToolSelected == true) {
|
||||
Overlays.editOverlay(voxelTool, {
|
||||
color: activeUIColor
|
||||
});
|
||||
} else {
|
||||
Overlays.editOverlay(voxelTool, {
|
||||
color: UIColor
|
||||
});
|
||||
}
|
||||
|
||||
clickedOnSomething = true;
|
||||
} else if (scaleSelector.clicked(event.x, event.y)) {
|
||||
clickedOnSomething = true;
|
||||
voxelSize = scaleSelector.scale;
|
||||
}
|
||||
|
||||
// Return if we clicked on the UI or the voxel tool is disabled
|
||||
if (clickedOnSomething || !voxelToolSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute the picking ray for the click
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
var resultVoxel = calculateVoxelFromIntersection(intersection, "add");
|
||||
|
||||
// Currently not in use, could randomly select a tree
|
||||
var treeIndex = Math.floor(Math.random() * treeTypes.length);
|
||||
|
||||
// Grow the first tree type
|
||||
growTree(resultVoxel.x, resultVoxel.y, resultVoxel.z, treeTypes[0]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(linePreviewTop);
|
||||
Overlays.deleteOverlay(linePreviewBottom);
|
||||
Overlays.deleteOverlay(linePreviewLeft);
|
||||
Overlays.deleteOverlay(linePreviewRight);
|
||||
scaleSelector.cleanup();
|
||||
Overlays.deleteOverlay(voxelTool);
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
Voxels.setPacketsPerSecond(10000);
|
|
@ -144,7 +144,7 @@ function shootTarget() {
|
|||
velocity: velocity,
|
||||
gravity: { x: 0, y: TARGET_GRAVITY, z: 0 },
|
||||
lifetime: TARGET_LIFETIME,
|
||||
damping: 0.99 });
|
||||
damping: 0.0001 });
|
||||
|
||||
// Record start time
|
||||
shotTime = new Date();
|
||||
|
@ -156,19 +156,6 @@ function shootTarget() {
|
|||
|
||||
|
||||
|
||||
function entityCollisionWithVoxel(entity, voxel, collision) {
|
||||
var HOLE_SIZE = 0.125;
|
||||
var entityProperties = Entities.getEntityProperties(entity);
|
||||
var position = entityProperties.position;
|
||||
Entities.deleteEntity(entity);
|
||||
// Make a hole in this voxel
|
||||
//Vec3.print("voxel penetration", collision.penetration);
|
||||
//Vec3.print("voxel contactPoint", collision.contactPoint);
|
||||
Voxels.eraseVoxel(collision.contactPoint.x, collision.contactPoint.y, collision.contactPoint.z, HOLE_SIZE);
|
||||
audioOptions.position = collision.contactPoint;
|
||||
Audio.playSound(impactSound, audioOptions);
|
||||
}
|
||||
|
||||
function entityCollisionWithEntity(entity1, entity2, collision) {
|
||||
score++;
|
||||
if (showScore) {
|
||||
|
@ -329,7 +316,6 @@ function scriptEnding() {
|
|||
MyAvatar.detachOne(gunModel);
|
||||
}
|
||||
|
||||
Entities.entityCollisionWithVoxel.connect(entityCollisionWithVoxel);
|
||||
Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
Script.update.connect(update);
|
||||
|
|
|
@ -221,13 +221,11 @@ function mousePressEvent(event) {
|
|||
|
||||
// Compute trajectories related values
|
||||
var pickRay = Camera.computePickRay(mouseLastX, mouseLastY);
|
||||
var voxelIntersection = Voxels.findRayIntersection(pickRay);
|
||||
var modelIntersection = Entities.findRayIntersection(pickRay);
|
||||
|
||||
position = Camera.getPosition();
|
||||
|
||||
var avatarTarget = MyAvatar.getTargetAvatarPosition();
|
||||
var voxelTarget = voxelIntersection.intersection;
|
||||
|
||||
|
||||
var distance = -1;
|
||||
|
@ -246,13 +244,6 @@ function mousePressEvent(event) {
|
|||
string = "Inspecting avatar";
|
||||
}
|
||||
|
||||
if ((distance == -1 || Vec3.length(Vec3.subtract(voxelTarget, position)) < distance) &&
|
||||
(voxelTarget.x != 0 || voxelTarget.y != 0 || voxelTarget.z != 0)) {
|
||||
distance = Vec3.length(Vec3.subtract(voxelTarget, position));
|
||||
center = voxelTarget;
|
||||
string = "Inspecting voxel";
|
||||
}
|
||||
|
||||
if (distance == -1) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ ModelImporter = function (opts) {
|
|||
this.mouseMoveEvent = function (event) {
|
||||
if (self._importing) {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
var intersection = Entities.findRayIntersection(pickRay);
|
||||
|
||||
var distance = 2;// * self._scale;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Grid = function(opts) {
|
|||
{ red: 255, green: 0, blue: 0 },
|
||||
];
|
||||
var colorIndex = 0;
|
||||
var gridAlpha = 1.0;
|
||||
var gridAlpha = 0.6;
|
||||
var origin = { x: 0, y: 0, z: 0 };
|
||||
var majorGridEvery = 5;
|
||||
var minorGridWidth = 0.2;
|
||||
|
@ -24,7 +24,7 @@ Grid = function(opts) {
|
|||
position: { x: 0 , y: 0, z: 0 },
|
||||
visible: true,
|
||||
color: colors[0],
|
||||
alpha: 1.0,
|
||||
alpha: gridAlpha,
|
||||
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
minorGridWidth: 0.1,
|
||||
majorGridEvery: 2,
|
||||
|
|
|
@ -181,7 +181,9 @@ spatialInformation = (function() {
|
|||
|
||||
// use the blocking version of findRayIntersection to avoid errors
|
||||
var pickRay = {origin: MyAvatar.position, direction: {x:0, y:-1, z:0}};
|
||||
return Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;;
|
||||
|
||||
// TODO: change this to use entities?
|
||||
return false; // Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ function mousePressEvent(event) {
|
|||
cancelLookAt();
|
||||
} else {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
var intersection = Entities.findRayIntersection(pickRay);
|
||||
if (intersection.intersects) {
|
||||
|
||||
// remember the old mode we were in
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
//
|
||||
// movingVoxel.js
|
||||
// examples
|
||||
//
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This sample script creates a voxel moving back and forth in a line
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var position = { x: 0, y: 0, z: 0 };
|
||||
var oldPosition = { x: 0, y: 0, z:0 };
|
||||
var size = 0.25;
|
||||
var direction = 1.0;
|
||||
var range = 2.0;
|
||||
var color = { r: 100, g: 50, b: 150 };
|
||||
var colorEdge = { r:255, g:250, b:175 };
|
||||
var frame = 0;
|
||||
var thisColor = color;
|
||||
|
||||
function moveVoxel(deltaTime) {
|
||||
frame++;
|
||||
if (frame % 3 == 0) {
|
||||
// Get a new position
|
||||
position.x += direction * size;
|
||||
if (position.x < 0) {
|
||||
direction *= -1.0;
|
||||
position.x = 0;
|
||||
thisColor = colorEdge;
|
||||
}
|
||||
if (position.x > range) {
|
||||
direction *= -1.0;
|
||||
position.x = range;
|
||||
thisColor = colorEdge;
|
||||
}
|
||||
// Create a new voxel
|
||||
Voxels.setVoxel(position.x, position.y, position.z, size, thisColor.r, thisColor.g, thisColor.b);
|
||||
// delete old voxel
|
||||
Voxels.eraseVoxel(oldPosition.x, oldPosition.y, oldPosition.z, size);
|
||||
// Copy old location to new
|
||||
oldPosition.x = position.x;
|
||||
oldPosition.y = position.y;
|
||||
oldPosition.z = position.z;
|
||||
thisColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
Voxels.setPacketsPerSecond(300);
|
||||
// Connect a call back that happens every frame
|
||||
Script.update.connect(moveVoxel);
|
|
@ -18,30 +18,6 @@ function mouseMoveEvent(event) {
|
|||
print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z);
|
||||
print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z);
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
if (!intersection.accurate) {
|
||||
print(">>> NOTE: intersection not accurate. will try calling Voxels.findRayIntersectionBlocking()");
|
||||
intersection = Voxels.findRayIntersectionBlocking(pickRay);
|
||||
print(">>> AFTER BLOCKING CALL intersection.accurate=" + intersection.accurate);
|
||||
}
|
||||
|
||||
if (intersection.intersects) {
|
||||
print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", "
|
||||
+ intersection.voxel.green + ", " + intersection.voxel.blue);
|
||||
print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", "
|
||||
+ intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s);
|
||||
print("intersection face=" + intersection.face);
|
||||
print("intersection distance=" + intersection.distance);
|
||||
print("intersection intersection.x/y/z=" + intersection.intersection.x + ", "
|
||||
+ intersection.intersection.y + ", " + intersection.intersection.z);
|
||||
|
||||
// also test the getVoxelAt() api which should find and return same voxel
|
||||
|
||||
var voxelAt = Voxels.getVoxelAt(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s);
|
||||
print("voxelAt.x/y/z/s=" + voxelAt.x + ", " + voxelAt.y + ", " + voxelAt.z + ": " + voxelAt.s);
|
||||
print("voxelAt.red/green/blue=" + voxelAt.red + ", " + voxelAt.green + ", " + voxelAt.blue);
|
||||
}
|
||||
|
||||
intersection = Entities.findRayIntersection(pickRay);
|
||||
if (!intersection.accurate) {
|
||||
print(">>> NOTE: intersection not accurate. will try calling Entities.findRayIntersectionBlocking()");
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
//
|
||||
// ribbon.js
|
||||
// examples
|
||||
//
|
||||
// Created by Andrzej Kapolka on 2/24/14.
|
||||
// Copyright 2014 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
|
||||
//
|
||||
|
||||
function vectorMultiply(vector, scalar) {
|
||||
return [ vector[0] * scalar, vector[1] * scalar, vector[2] * scalar ];
|
||||
}
|
||||
|
||||
function vectorAdd(firstVector, secondVector) {
|
||||
return [ firstVector[0] + secondVector[0], firstVector[1] + secondVector[1], firstVector[2] + secondVector[2] ];
|
||||
}
|
||||
|
||||
function vectorSubtract(firstVector, secondVector) {
|
||||
return [ firstVector[0] - secondVector[0], firstVector[1] - secondVector[1], firstVector[2] - secondVector[2] ];
|
||||
}
|
||||
|
||||
function vectorCross(firstVector, secondVector) {
|
||||
return [ firstVector[1] * secondVector[2] - firstVector[2] * secondVector[1],
|
||||
firstVector[2] * secondVector[0] - firstVector[0] * secondVector[2],
|
||||
firstVector[0] * secondVector[1] - firstVector[1] * secondVector[0] ];
|
||||
}
|
||||
|
||||
function vectorLength(vector) {
|
||||
return Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]);
|
||||
}
|
||||
|
||||
function vectorNormalize(vector) {
|
||||
return vectorMultiply(vector, 1.0 / vectorLength(vector));
|
||||
}
|
||||
|
||||
function vectorClone(vector) {
|
||||
return [ vector[0], vector[1], vector[2] ];
|
||||
}
|
||||
|
||||
function mix(first, second, amount) {
|
||||
return first + (second - first) * amount;
|
||||
}
|
||||
|
||||
function vectorMix(firstVector, secondVector, amount) {
|
||||
return vectorAdd(firstVector, vectorMultiply(vectorSubtract(secondVector, firstVector), amount));
|
||||
}
|
||||
|
||||
function randomVector(minVector, maxVector) {
|
||||
return [ mix(minVector[0], maxVector[0], Math.random()), mix(minVector[1], maxVector[1], Math.random()),
|
||||
mix(minVector[2], maxVector[2], Math.random()) ];
|
||||
}
|
||||
|
||||
function applyToLine(start, end, granularity, fn) {
|
||||
// determine the number of steps from the maximum length
|
||||
var steps = Math.max(
|
||||
Math.abs(Math.floor(start[0] / granularity) - Math.floor(end[0] / granularity)),
|
||||
Math.abs(Math.floor(start[1] / granularity) - Math.floor(end[1] / granularity)),
|
||||
Math.abs(Math.floor(start[2] / granularity) - Math.floor(end[2] / granularity)));
|
||||
var position = vectorClone(start);
|
||||
var increment = vectorMultiply(vectorSubtract(end, start), 1.0 / steps);
|
||||
for (var i = 0; i <= steps; i++) {
|
||||
fn(granularity * Math.floor(position[0] / granularity),
|
||||
granularity * Math.floor(position[1] / granularity),
|
||||
granularity * Math.floor(position[2] / granularity),
|
||||
granularity);
|
||||
position = vectorAdd(position, increment);
|
||||
}
|
||||
}
|
||||
|
||||
function drawLine(start, end, color, granularity) {
|
||||
applyToLine(start, end, granularity, function(x, y, z, scale) {
|
||||
Voxels.setVoxel(x, y, z, scale, color[0], color[1], color[2]);
|
||||
});
|
||||
}
|
||||
|
||||
function eraseLine(start, end, granularity) {
|
||||
applyToLine(start, end, granularity, function(x, y, z, scale) {
|
||||
Voxels.eraseVoxel(x, y, z, scale);
|
||||
});
|
||||
}
|
||||
|
||||
function getHueColor(hue) {
|
||||
// see http://en.wikipedia.org/wiki/HSL_and_HSV
|
||||
var hPrime = hue / 60.0;
|
||||
var x = Math.floor(255.0 * (1.0 - Math.abs(hPrime % 2.0 - 1.0)));
|
||||
if (hPrime < 1) {
|
||||
return [255, x, 0];
|
||||
|
||||
} else if (hPrime < 2) {
|
||||
return [x, 255, 0];
|
||||
|
||||
} else if (hPrime < 3) {
|
||||
return [0, 255, x];
|
||||
|
||||
} else if (hPrime < 4) {
|
||||
return [0, x, 255];
|
||||
|
||||
} else if (hPrime < 5) {
|
||||
return [x, 0, 255];
|
||||
|
||||
} else { // hPrime < 6
|
||||
return [255, 0, x];
|
||||
}
|
||||
}
|
||||
|
||||
var UNIT_MIN = [-1.0, -1.0, -1.0];
|
||||
var UNIT_MAX = [1.0, 1.0, 1.0];
|
||||
|
||||
var EPSILON = 0.00001;
|
||||
|
||||
var BOUNDS_MIN = [5.0, 0.0, 5.0];
|
||||
var BOUNDS_MAX = [15.0, 10.0, 15.0];
|
||||
|
||||
var GRANULARITY = 1.0 / 16.0;
|
||||
|
||||
var WIDTH = 0.5;
|
||||
|
||||
var HISTORY_LENGTH = 300;
|
||||
|
||||
var stateHistory = [];
|
||||
var position;
|
||||
var velocity;
|
||||
var hueAngle = 0;
|
||||
var smoothedOffset;
|
||||
|
||||
function step(deltaTime) {
|
||||
if (stateHistory.length === 0) {
|
||||
// start at a random position within the bounds, with a random velocity
|
||||
position = randomVector(BOUNDS_MIN, BOUNDS_MAX);
|
||||
do {
|
||||
velocity = randomVector(UNIT_MIN, UNIT_MAX);
|
||||
} while (vectorLength(velocity) < EPSILON);
|
||||
velocity = vectorMultiply(velocity, GRANULARITY * 0.5 / vectorLength(velocity));
|
||||
smoothedOffset = [0.0, 0.0, 0.0];
|
||||
}
|
||||
|
||||
var right = vectorCross(velocity, [0.0, 1.0, 0.0]);
|
||||
if (vectorLength(right) < EPSILON) {
|
||||
right = [1.0, 0.0, 0.0];
|
||||
} else {
|
||||
right = vectorNormalize(right);
|
||||
}
|
||||
var up = vectorNormalize(vectorCross(right, velocity));
|
||||
var ANGULAR_SPEED = 2.0;
|
||||
var radians = hueAngle * Math.PI * ANGULAR_SPEED / 180.0;
|
||||
var offset = vectorAdd(vectorMultiply(right, WIDTH * Math.cos(radians)), vectorMultiply(up, WIDTH * Math.sin(radians)));
|
||||
var OFFSET_SMOOTHING = 0.9;
|
||||
smoothedOffset = vectorMix(offset, smoothedOffset, OFFSET_SMOOTHING);
|
||||
|
||||
var state = { start: vectorAdd(position, smoothedOffset), end: vectorSubtract(position, smoothedOffset) };
|
||||
drawLine(state.start, state.end, getHueColor(hueAngle), GRANULARITY);
|
||||
stateHistory.push(state);
|
||||
if (stateHistory.length > HISTORY_LENGTH) {
|
||||
var last = stateHistory.shift();
|
||||
eraseLine(last.start, last.end, GRANULARITY);
|
||||
}
|
||||
|
||||
// update position, check against bounds
|
||||
position = vectorAdd(position, velocity);
|
||||
for (var i = 0; i < 3; i++) {
|
||||
if (position[i] < BOUNDS_MIN[i]) {
|
||||
velocity[i] = -velocity[i];
|
||||
position[i] += 2.0 * (BOUNDS_MIN[i] - position[i]);
|
||||
|
||||
} else if (position[i] > BOUNDS_MAX[i]) {
|
||||
velocity[i] = -velocity[i];
|
||||
position[i] += 2.0 * (BOUNDS_MAX[i] - position[i]);
|
||||
}
|
||||
}
|
||||
var MAX_HUE_ANGLE = 360;
|
||||
hueAngle = (hueAngle + 1) % MAX_HUE_ANGLE;
|
||||
}
|
||||
|
||||
Script.update.connect(step);
|
|
@ -1,272 +0,0 @@
|
|||
// rockPaperScissorsCells.js
|
||||
// examples
|
||||
//
|
||||
// Created by Ben Arnold on 7/16/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This sample script creates a voxel wall that simulates the Rock Paper Scissors cellular
|
||||
// automata. http://www.gamedev.net/blog/844/entry-2249737-another-cellular-automaton-video/
|
||||
// If multiple instances of this script are run, they will combine into a larger wall.
|
||||
// NOTE: You must run each instance one at a time. If they all start at once there are race conditions.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var NUMBER_OF_CELLS_EACH_DIMENSION = 48;
|
||||
var NUMBER_OF_CELLS_REGION_EACH_DIMESION = 16;
|
||||
var REGIONS_EACH_DIMENSION = NUMBER_OF_CELLS_EACH_DIMENSION / NUMBER_OF_CELLS_REGION_EACH_DIMESION;
|
||||
|
||||
var isLocal = false;
|
||||
|
||||
var currentCells = [];
|
||||
var nextCells = [];
|
||||
|
||||
var cornerPosition = {x: 100, y: 0, z: 0 }
|
||||
var position = {x: 0, y: 0, z: 0 };
|
||||
|
||||
var METER_LENGTH = 1;
|
||||
var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION;
|
||||
|
||||
var viewerPosition = {x: cornerPosition.x + (NUMBER_OF_CELLS_EACH_DIMENSION / 2) * cellScale, y: cornerPosition.y + (NUMBER_OF_CELLS_EACH_DIMENSION / 2) * cellScale, z: cornerPosition.z };
|
||||
|
||||
viewerPosition.z += 50;
|
||||
var yaw = 0;
|
||||
var orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0);
|
||||
|
||||
//Feel free to add new cell types here. It can be more than three.
|
||||
var cellTypes = [];
|
||||
cellTypes[0] = { r: 255, g: 0, b: 0 };
|
||||
cellTypes[1] = { r: 0, g: 255, b: 0 };
|
||||
cellTypes[2] = { r: 0, g:0, b: 255 };
|
||||
cellTypes[3] = { r: 0, g: 255, b: 255 };
|
||||
|
||||
|
||||
//Check for free region for AC
|
||||
var regionMarkerX = -1;
|
||||
var regionMarkerY = -1;
|
||||
var regionMarkerI = -1;
|
||||
var regionMarkerJ = -1;
|
||||
|
||||
var regionMarkerColor = {r: 254, g: 0, b: 253};
|
||||
|
||||
function setRegionToColor(startX, startY, width, height, color) {
|
||||
for (var i = startY; i < startY + height; i++) {
|
||||
for (var j = startX; j < startX + width; j++) {
|
||||
|
||||
currentCells[i][j] = { changed: true, type: color };
|
||||
|
||||
// put the same value in the nextCells array for first board draw
|
||||
nextCells[i][j] = { changed: true, type: color };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
for (var i = 0; i < REGIONS_EACH_DIMENSION; i++) {
|
||||
for (var j = 0; j < REGIONS_EACH_DIMENSION; j++) {
|
||||
var x = cornerPosition.x + (j) * cellScale;
|
||||
var y = cornerPosition.y + (i + NUMBER_OF_CELLS_EACH_DIMENSION) * cellScale;
|
||||
var z = cornerPosition.z;
|
||||
var voxel = Voxels.getVoxelAt(x, y, z, cellScale);
|
||||
if (voxel.x != x || voxel.y != y || voxel.z != z || voxel.s != cellScale ||
|
||||
voxel.red != regionMarkerColor.r || voxel.green != regionMarkerColor.g || voxel.blue != regionMarkerColor.b) {
|
||||
regionMarkerX = x;
|
||||
regionMarkerY = y;
|
||||
regionMarkerI = i;
|
||||
regionMarkerJ = j;
|
||||
i = REGIONS_EACH_DIMENSION; //force quit loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Didnt find an open spot, end script
|
||||
if (regionMarkerX == -1) {
|
||||
Script.stop();
|
||||
}
|
||||
|
||||
position.x = cornerPosition.x + regionMarkerJ * NUMBER_OF_CELLS_REGION_EACH_DIMESION;
|
||||
position.y = cornerPosition.y + regionMarkerI * NUMBER_OF_CELLS_REGION_EACH_DIMESION;
|
||||
position.z = cornerPosition.z;
|
||||
|
||||
Voxels.setVoxel(regionMarkerX, regionMarkerY, cornerPosition.z, cellScale, regionMarkerColor.r, regionMarkerColor.g, regionMarkerColor.b);
|
||||
|
||||
for (var i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) {
|
||||
// create the array to hold this row
|
||||
currentCells[i] = [];
|
||||
|
||||
// create the array to hold this row in the nextCells array
|
||||
nextCells[i] = [];
|
||||
}
|
||||
|
||||
var width = NUMBER_OF_CELLS_REGION_EACH_DIMESION / 2;
|
||||
setRegionToColor(0, 0, width, width, 0);
|
||||
setRegionToColor(0, width, width, width, 1);
|
||||
setRegionToColor(width, width, width, width, 2);
|
||||
setRegionToColor(width, 0, width, width, 3);
|
||||
}
|
||||
|
||||
function updateCells() {
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var cell;
|
||||
var y = 0;
|
||||
var x = 0;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) {
|
||||
for (j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) {
|
||||
|
||||
cell = currentCells[i][j];
|
||||
|
||||
var r = Math.floor(Math.random() * 8);
|
||||
|
||||
switch (r){
|
||||
case 0:
|
||||
y = i - 1;
|
||||
x = j - 1;
|
||||
break;
|
||||
case 1:
|
||||
y = i;
|
||||
x = j-1;
|
||||
break;
|
||||
case 2:
|
||||
y = i + 1;
|
||||
x = j - 1;
|
||||
break;
|
||||
case 3:
|
||||
y = i + 1;
|
||||
x = j;
|
||||
break;
|
||||
case 4:
|
||||
y = i + 1;
|
||||
x = j + 1;
|
||||
break;
|
||||
case 5:
|
||||
y = i;
|
||||
x = j + 1;
|
||||
break;
|
||||
case 6:
|
||||
y = i - 1;
|
||||
x = j + 1;
|
||||
break;
|
||||
case 7:
|
||||
y = i - 1;
|
||||
x = j;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
//check the voxel grid instead of local array when on the edge
|
||||
if (x == -1 || x == NUMBER_OF_CELLS_REGION_EACH_DIMESION ||
|
||||
y == -1 || y == NUMBER_OF_CELLS_REGION_EACH_DIMESION) {
|
||||
|
||||
var voxel = Voxels.getVoxelAt(position.x + x * cellScale, position.y + y * cellScale, position.z, cellScale);
|
||||
var predatorCellType = ((cell.type + 1) % cellTypes.length);
|
||||
var predatorCellColor = cellTypes[predatorCellType];
|
||||
if (voxel.red == predatorCellColor.r && voxel.green == predatorCellColor.g && voxel.blue == predatorCellColor.b) {
|
||||
nextCells[i][j].type = predatorCellType;
|
||||
nextCells[i][j].changed = true;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (currentCells[y][x].type == ((cell.type + 1) % cellTypes.length)) {
|
||||
nextCells[i][j].type = currentCells[y][x].type;
|
||||
nextCells[i][j].changed = true;
|
||||
} else {
|
||||
//indicate no update
|
||||
nextCells[i][j].changed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) {
|
||||
for (j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) {
|
||||
if (nextCells[i][j].changed == true) {
|
||||
// there has been a change to this cell, change the value in the currentCells array
|
||||
currentCells[i][j].type = nextCells[i][j].type;
|
||||
currentCells[i][j].changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendNextCells() {
|
||||
for (var i = 0; i < NUMBER_OF_CELLS_REGION_EACH_DIMESION; i++) {
|
||||
for (var j = 0; j < NUMBER_OF_CELLS_REGION_EACH_DIMESION; j++) {
|
||||
if (nextCells[i][j].changed == true) {
|
||||
// there has been a change to the state of this cell, send it
|
||||
|
||||
// find the x and y position for this voxel, z = 0
|
||||
var x = j * cellScale;
|
||||
var y = i * cellScale;
|
||||
var type = nextCells[i][j].type;
|
||||
|
||||
// queue a packet to add a voxel for the new cell
|
||||
Voxels.setVoxel(position.x + x, position.y + y, position.z, cellScale, cellTypes[type].r, cellTypes[type].g, cellTypes[type].b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sentFirstBoard = false;
|
||||
var voxelViewerInit = false;
|
||||
|
||||
var UPDATES_PER_SECOND = 6.0;
|
||||
var frameIndex = 1.0;
|
||||
var oldFrameIndex = 0;
|
||||
|
||||
var framesToWait = UPDATES_PER_SECOND;
|
||||
|
||||
function step(deltaTime) {
|
||||
|
||||
if (isLocal == false) {
|
||||
if (voxelViewerInit == false) {
|
||||
VoxelViewer.setPosition(viewerPosition);
|
||||
VoxelViewer.setOrientation(orientation);
|
||||
voxelViewerInit = true;
|
||||
}
|
||||
VoxelViewer.queryOctree();
|
||||
}
|
||||
|
||||
frameIndex += deltaTime * UPDATES_PER_SECOND;
|
||||
if (Math.floor(frameIndex) == oldFrameIndex) {
|
||||
return;
|
||||
}
|
||||
oldFrameIndex++;
|
||||
|
||||
if (frameIndex <= framesToWait) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sentFirstBoard) {
|
||||
// we've already sent the first full board, perform a step in time
|
||||
updateCells();
|
||||
} else {
|
||||
// this will be our first board send
|
||||
sentFirstBoard = true;
|
||||
init();
|
||||
}
|
||||
|
||||
if (isLocal == false) {
|
||||
VoxelViewer.queryOctree();
|
||||
}
|
||||
sendNextCells();
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
Voxels.eraseVoxel(regionMarkerX, regionMarkerY, position.z, cellScale);
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
Script.update.connect(step);
|
||||
Voxels.setPacketsPerSecond(2000);
|
||||
|
||||
// test for local...
|
||||
Menu.isOptionChecked("Voxels");
|
||||
isLocal = true; // will only get here on local client
|
|
@ -137,7 +137,7 @@ function checkControllerSide(whichSide) {
|
|||
gravity: { x: 0, y: 0, z: 0},
|
||||
inHand: true,
|
||||
radius: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 },
|
||||
damping: 0.999,
|
||||
damping: 0.00001,
|
||||
color: HELD_COLOR,
|
||||
|
||||
lifetime: 600 // 10 seconds - same as default, not needed but here as an example
|
||||
|
|
|
@ -12,7 +12,7 @@ var properties = {
|
|||
velocity: { x: 0, y: 0, z: 0},
|
||||
gravity: { x: 0, y: -0.05, z: 0},
|
||||
radius: radius,
|
||||
damping: 0.999,
|
||||
damping: 0.00001,
|
||||
color: { red: 200, green: 0, blue: 0 },
|
||||
lifetime: 60
|
||||
};
|
||||
|
@ -22,4 +22,4 @@ position.x -= radius * 1.0;
|
|||
properties.position = position;
|
||||
var newEntityTwo = Entities.addEntity(properties);
|
||||
|
||||
Script.stop(); // no need to run anymore
|
||||
Script.stop(); // no need to run anymore
|
||||
|
|
|
@ -1,226 +0,0 @@
|
|||
|
||||
|
||||
|
||||
var wallX = 8000;
|
||||
var wallY = 8000;
|
||||
var wallZ = 8000;//location
|
||||
|
||||
|
||||
var VOXELSIZE=12;//size of each voxel
|
||||
|
||||
var FACTOR = 0.75;
|
||||
|
||||
var loud=1.0;
|
||||
var maxLoud=500;
|
||||
var minLoud=200;//range of loudness
|
||||
|
||||
|
||||
|
||||
var maxB={color:225,direction:0,speed:1};
|
||||
var minB={color:50,direction:1,speed:1};
|
||||
var maxG={color:200,direction:0,speed:1};
|
||||
var minG={color:30,direction:1,speed:1};
|
||||
var maxR={color:255,direction:0,speed:1};
|
||||
var minR={color:150,direction:1,speed:1};//color objects
|
||||
var addVoxArray=[];
|
||||
var removeVoxArray=[];
|
||||
var numAddVox=0;
|
||||
var numRemoveVox=0;//array for voxels removed and added
|
||||
|
||||
|
||||
var height;
|
||||
var wallWidth=34;
|
||||
var wallHeight=25;
|
||||
var maxHeight=wallHeight;
|
||||
var minHeight=0;//properties of wall
|
||||
|
||||
|
||||
var heightSamplesArray=[];
|
||||
var sampleIndex=0;//declare new array of heights
|
||||
|
||||
var direction=1;
|
||||
|
||||
|
||||
|
||||
|
||||
//initiate and fill array of heights
|
||||
for(var k=0;k<wallWidth;k++)
|
||||
{
|
||||
heightSamplesArray[k]=0;
|
||||
}
|
||||
|
||||
|
||||
//send objects to function changeColor
|
||||
function scratch()
|
||||
{
|
||||
|
||||
|
||||
changeColor(maxB);
|
||||
changeColor(minB);
|
||||
changeColor(maxG);
|
||||
changeColor(minG);
|
||||
changeColor(maxR);
|
||||
changeColor(minR);
|
||||
|
||||
//calculates loudness
|
||||
var audioAverageLoudness = MyAvatar.audioAverageLoudness * FACTOR;
|
||||
|
||||
|
||||
loud = Math.log(audioAverageLoudness) / 5.0 * 255.0;
|
||||
|
||||
print("loud="+ loud);
|
||||
|
||||
|
||||
var scalingfactor=(loud-minLoud)/(maxLoud-minLoud);
|
||||
if(scalingfactor<0)
|
||||
{
|
||||
scalingfactor=0;
|
||||
}
|
||||
if(scalingfactor>1)
|
||||
{
|
||||
scalingfactor=1;
|
||||
}
|
||||
|
||||
//creates diff shades for diff levels of volume
|
||||
|
||||
var green=(maxG.color-minG.color)*scalingfactor+minG.color;
|
||||
var blue=(maxB.color-minB.color)*scalingfactor+minB.color;
|
||||
var red=(maxR.color-minR.color)*scalingfactor+minR.color;
|
||||
height=(maxHeight-minHeight)*scalingfactor+minHeight;
|
||||
|
||||
|
||||
//sets height at position sampleIndex
|
||||
heightSamplesArray[sampleIndex]=height;
|
||||
|
||||
|
||||
|
||||
|
||||
if(loud==Number.NEGATIVE_INFINITY)
|
||||
{
|
||||
green=minG.color;
|
||||
blue=minB.color;
|
||||
red=minR.color;
|
||||
|
||||
}
|
||||
|
||||
|
||||
var k=sampleIndex;
|
||||
|
||||
//add&remove voxels
|
||||
|
||||
for(var i=wallWidth-1;i>=0;i--)
|
||||
{
|
||||
|
||||
for(var j=0;j<wallHeight;j++)
|
||||
|
||||
{
|
||||
if(j<=heightSamplesArray[k])
|
||||
{
|
||||
addVoxArray[numAddVox]={x:wallX+i*VOXELSIZE, y:wallY+j*VOXELSIZE, z:wallZ};
|
||||
|
||||
numAddVox++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
removeVoxArray[numRemoveVox]={x:wallX+i*VOXELSIZE, y:wallY+j*VOXELSIZE, z:wallZ};
|
||||
|
||||
numRemoveVox++;
|
||||
}
|
||||
|
||||
}
|
||||
k--;
|
||||
if(k<0)
|
||||
{
|
||||
k=wallWidth-1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(var k=0;k<numAddVox;k++)
|
||||
{
|
||||
Voxels.setVoxel(addVoxArray[k].x,addVoxArray[k].y,addVoxArray[k].z,VOXELSIZE, red, green, blue);
|
||||
}
|
||||
|
||||
for(var k=0;k<numRemoveVox;k++)
|
||||
{
|
||||
Voxels.eraseVoxel(removeVoxArray[k].x,removeVoxArray[k].y,removeVoxArray[k].z,VOXELSIZE);
|
||||
}
|
||||
|
||||
numAddVox=0;
|
||||
numRemoveVox=0;
|
||||
|
||||
sampleIndex++;
|
||||
if(sampleIndex>=wallWidth)
|
||||
{
|
||||
sampleIndex=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//color properties (shade, direction, speed)
|
||||
|
||||
function changeColor(color)
|
||||
{
|
||||
|
||||
if (color.direction==1)
|
||||
{
|
||||
if(color.color<255)
|
||||
{
|
||||
color.color+=(color.speed);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
color.direction=0;
|
||||
}
|
||||
|
||||
}
|
||||
else if(color.direction==0)
|
||||
{
|
||||
if(color.color>0)
|
||||
{
|
||||
color.color-=(color.speed);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
color.direction=1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Script.update.connect(scratch);
|
||||
Voxels.setPacketsPerSecond(20000);
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
|
||||
|
||||
|
||||
var wallX = 700;
|
||||
var wallY = 700;
|
||||
var wallZ = 700;//location
|
||||
|
||||
var VOXELSIZE=8;
|
||||
var red=225;
|
||||
var blue=0;
|
||||
var green=0;//color brightness
|
||||
var currentStep=0;//counting number of steps
|
||||
var direction=1;//left to right color change
|
||||
var height=8;
|
||||
var width=8;
|
||||
|
||||
|
||||
var currentStep=0;
|
||||
|
||||
|
||||
|
||||
|
||||
function step()
|
||||
{
|
||||
|
||||
|
||||
|
||||
currentStep++;
|
||||
|
||||
if(currentStep>6000)//how long it will run
|
||||
Script.stop();
|
||||
|
||||
|
||||
for(var i=0;i<width;i++)
|
||||
{
|
||||
for(var j=0;j<height;j++)
|
||||
{
|
||||
|
||||
Voxels.setVoxel(wallX+i*VOXELSIZE, wallY+j*VOXELSIZE, wallZ, VOXELSIZE, red,green,blue);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (direction==1)
|
||||
{
|
||||
if(blue<255)
|
||||
{
|
||||
blue++;
|
||||
red--;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
direction=0;
|
||||
}
|
||||
|
||||
}
|
||||
else if(direction==0)
|
||||
{
|
||||
if(blue>0)
|
||||
{
|
||||
blue--;
|
||||
red++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
direction=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Script.update.connect(step);
|
||||
Voxels.setPacketsPerSecond(20000);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ endif()
|
|||
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
|
||||
|
||||
# link required hifi libraries
|
||||
link_hifi_libraries(shared octree voxels gpu model fbx metavoxels networking entities avatars audio animation script-engine physics
|
||||
link_hifi_libraries(shared octree environment gpu model fbx metavoxels networking entities avatars audio animation script-engine physics
|
||||
render-utils entities-renderer)
|
||||
|
||||
# find any optional and required libraries
|
||||
|
|
|
@ -5,14 +5,23 @@
|
|||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 1/21/14.
|
||||
// Update by Ryan Huffman on 12/30/14.
|
||||
// Copyright 2013 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
|
||||
//
|
||||
|
||||
varying vec2 modelCoords;
|
||||
|
||||
// Squared distance from center of 1x1 square to an edge along a single axis (0.5 * 0.5)
|
||||
const float SQUARED_DISTANCE_TO_EDGE = 0.25;
|
||||
|
||||
void main(void) {
|
||||
// use the standard exponential fog calculation
|
||||
const float FOG_DENSITY = 0.5;
|
||||
gl_FragColor = vec4(gl_Color.rgb, exp(-FOG_DENSITY / gl_FragCoord.w));
|
||||
// Squared distance from grid center - this assumes the grid lines are from
|
||||
// 0.0 ... 1.0 in model space.
|
||||
float sqDist = pow(modelCoords.x - 0.5, 2) + pow(modelCoords.y - 0.5, 2);
|
||||
float alpha = max(0, SQUARED_DISTANCE_TO_EDGE - sqDist) / SQUARED_DISTANCE_TO_EDGE;
|
||||
alpha *= gl_Color.a;
|
||||
gl_FragColor = vec4(gl_Color.rgb, alpha);
|
||||
}
|
||||
|
|
20
interface/resources/shaders/grid.vert
Normal file
20
interface/resources/shaders/grid.vert
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// grid.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Ryan Huffman on 12/30/14
|
||||
// Copyright 2014 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
|
||||
//
|
||||
|
||||
varying vec2 modelCoords;
|
||||
|
||||
void main(void) {
|
||||
modelCoords = gl_Vertex.xy;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xy, 0, 1);
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
|
@ -62,7 +62,6 @@
|
|||
#include <GlowEffect.h>
|
||||
#include <HFActionEvent.h>
|
||||
#include <HFBackEvent.h>
|
||||
#include <LocalVoxelsList.h>
|
||||
#include <LogHandler.h>
|
||||
#include <MainWindow.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
|
@ -152,10 +151,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_frameCount(0),
|
||||
_fps(60.0f),
|
||||
_justStarted(true),
|
||||
_voxelImportDialog(NULL),
|
||||
_voxelImporter(),
|
||||
_importSucceded(false),
|
||||
_sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard),
|
||||
#ifdef USE_BULLET_PHYSICS
|
||||
_physicsEngine(glm::vec3(0.0f)),
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
|
@ -163,7 +158,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_entityCollisionSystem(),
|
||||
_entityClipboardRenderer(false, this, this),
|
||||
_entityClipboard(),
|
||||
_wantToKillLocalVoxels(false),
|
||||
_viewFrustum(),
|
||||
_lastQueriedViewFrustum(),
|
||||
_lastQueriedTime(usecTimestampNow()),
|
||||
|
@ -179,9 +173,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_isTouchPressed(false),
|
||||
_mousePressed(false),
|
||||
_audio(),
|
||||
_enableProcessVoxelsThread(true),
|
||||
_enableProcessOctreeThread(true),
|
||||
_octreeProcessor(),
|
||||
_voxelHideShowThread(&_voxels),
|
||||
_packetsPerSecond(0),
|
||||
_bytesPerSecond(0),
|
||||
_nodeBoundsDisplay(this),
|
||||
|
@ -279,8 +272,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
connect(nodeList, &NodeList::nodeAdded, this, &Application::nodeAdded);
|
||||
connect(nodeList, &NodeList::nodeKilled, this, &Application::nodeKilled);
|
||||
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
|
||||
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer)));
|
||||
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer)));
|
||||
connect(nodeList, &NodeList::uuidChanged, _myAvatar, &MyAvatar::setSessionUUID);
|
||||
connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset);
|
||||
|
||||
|
@ -317,10 +308,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_settings = new QSettings(this);
|
||||
_numChangedSettings = 0;
|
||||
|
||||
// Check to see if the user passed in a command line option for loading a local
|
||||
// Voxel File.
|
||||
_voxelsFilename = getCmdOption(argc, constArgv, "-i");
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA WsaData;
|
||||
int wsaresult = WSAStartup(MAKEWORD(2,2), &WsaData);
|
||||
|
@ -328,11 +315,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
// tell the NodeList instance who to tell the domain server we care about
|
||||
nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer
|
||||
<< NodeType::VoxelServer << NodeType::EntityServer
|
||||
<< NodeType::EntityServer
|
||||
<< NodeType::MetavoxelServer);
|
||||
|
||||
// connect to the packet sent signal of the _voxelEditSender and the _entityEditSender
|
||||
connect(&_voxelEditSender, &VoxelEditPacketSender::packetSent, this, &Application::packetSent);
|
||||
// connect to the packet sent signal of the _entityEditSender
|
||||
connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent);
|
||||
|
||||
// move the silentNodeTimer to the _nodeThread
|
||||
|
@ -377,8 +363,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
// initialization continues in initializeGL when OpenGL context is ready
|
||||
|
||||
// Tell our voxel edit sender about our known jurisdictions
|
||||
_voxelEditSender.setVoxelServerJurisdictions(&_voxelServerJurisdictions);
|
||||
// Tell our entity edit sender about our known jurisdictions
|
||||
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
|
||||
|
||||
// For now we're going to set the PPS for outbound packets to be super high, this is
|
||||
|
@ -390,9 +375,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
_overlays.init(glCanvas.data()); // do this before scripts load
|
||||
|
||||
LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree());
|
||||
LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard);
|
||||
|
||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
||||
connect(_runningScriptsWidget, &RunningScriptsWidget::stopScriptName, this, &Application::stopScript);
|
||||
|
||||
|
@ -450,9 +432,6 @@ Application::~Application() {
|
|||
// make sure we don't call the idle timer any more
|
||||
delete idleTimer;
|
||||
|
||||
_sharedVoxelSystem.changeTree(new VoxelTree);
|
||||
delete _voxelImportDialog;
|
||||
|
||||
// let the avatar mixer know we're out
|
||||
MyAvatar::sendKillAvatar();
|
||||
|
||||
|
@ -471,11 +450,8 @@ Application::~Application() {
|
|||
_audio.thread()->wait();
|
||||
|
||||
_octreeProcessor.terminate();
|
||||
_voxelHideShowThread.terminate();
|
||||
_voxelEditSender.terminate();
|
||||
_entityEditSender.terminate();
|
||||
|
||||
VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown
|
||||
Menu::getInstance()->deleteLater();
|
||||
|
||||
_myAvatar = NULL;
|
||||
|
@ -485,9 +461,6 @@ void Application::saveSettings() {
|
|||
Menu::getInstance()->saveSettings();
|
||||
_rearMirrorTools->saveSettings(_settings);
|
||||
|
||||
if (_voxelImportDialog) {
|
||||
_voxelImportDialog->saveSettings(_settings);
|
||||
}
|
||||
_settings->sync();
|
||||
_numChangedSettings = 0;
|
||||
}
|
||||
|
@ -570,15 +543,9 @@ void Application::initializeGL() {
|
|||
init();
|
||||
qDebug( "init() complete.");
|
||||
|
||||
// create thread for parsing of voxel data independent of the main network and rendering threads
|
||||
_octreeProcessor.initialize(_enableProcessVoxelsThread);
|
||||
_voxelEditSender.initialize(_enableProcessVoxelsThread);
|
||||
_voxelHideShowThread.initialize(_enableProcessVoxelsThread);
|
||||
_entityEditSender.initialize(_enableProcessVoxelsThread);
|
||||
|
||||
if (_enableProcessVoxelsThread) {
|
||||
qDebug("Voxel parsing thread created.");
|
||||
}
|
||||
// create thread for parsing of octee data independent of the main network and rendering threads
|
||||
_octreeProcessor.initialize(_enableProcessOctreeThread);
|
||||
_entityEditSender.initialize(_enableProcessOctreeThread);
|
||||
|
||||
// call our timer function every second
|
||||
QTimer* timer = new QTimer(this);
|
||||
|
@ -801,10 +768,6 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum)
|
|||
|
||||
void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) {
|
||||
foreach(NodeType_t type, destinationNodeTypes) {
|
||||
// Intercept data to voxel server when voxels are disabled
|
||||
if (type == NodeType::VoxelServer && !Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Perform the broadcast for one type
|
||||
int nReceivingNodes = NodeList::getInstance()->broadcastToNodes(packet, NodeSet() << type);
|
||||
|
@ -816,9 +779,8 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod
|
|||
case NodeType::AvatarMixer:
|
||||
channel = BandwidthMeter::AVATARS;
|
||||
break;
|
||||
case NodeType::VoxelServer:
|
||||
case NodeType::EntityServer:
|
||||
channel = BandwidthMeter::VOXELS;
|
||||
channel = BandwidthMeter::OCTREE;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
|
@ -1097,11 +1059,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
Menu::getInstance()->triggerOption(MenuOption::DisplayFrustum);
|
||||
}
|
||||
break;
|
||||
case Qt::Key_V:
|
||||
if (isShifted) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::Voxels);
|
||||
}
|
||||
break;
|
||||
case Qt::Key_P:
|
||||
Menu::getInstance()->triggerOption(MenuOption::FirstPerson);
|
||||
break;
|
||||
|
@ -1446,7 +1403,7 @@ void Application::dropEvent(QDropEvent *event) {
|
|||
void Application::sendPingPackets() {
|
||||
QByteArray pingPacket = NodeList::getInstance()->constructPingPacket();
|
||||
controlledBroadcastToNodes(pingPacket, NodeSet()
|
||||
<< NodeType::VoxelServer << NodeType::EntityServer
|
||||
<< NodeType::EntityServer
|
||||
<< NodeType::AudioMixer << NodeType::AvatarMixer
|
||||
<< NodeType::MetavoxelServer);
|
||||
}
|
||||
|
@ -1592,63 +1549,10 @@ void Application::setEnableVRMode(bool enableVRMode) {
|
|||
resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight());
|
||||
}
|
||||
|
||||
void Application::setRenderVoxels(bool voxelRender) {
|
||||
_voxelEditSender.setShouldSend(voxelRender);
|
||||
if (!voxelRender) {
|
||||
doKillLocalVoxels();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::setLowVelocityFilter(bool lowVelocityFilter) {
|
||||
SixenseManager::getInstance().setLowVelocityFilter(lowVelocityFilter);
|
||||
}
|
||||
|
||||
void Application::doKillLocalVoxels() {
|
||||
_wantToKillLocalVoxels = true;
|
||||
}
|
||||
|
||||
void Application::removeVoxel(glm::vec3 position,
|
||||
float scale) {
|
||||
VoxelDetail voxel;
|
||||
voxel.x = position.x / TREE_SCALE;
|
||||
voxel.y = position.y / TREE_SCALE;
|
||||
voxel.z = position.z / TREE_SCALE;
|
||||
voxel.s = scale / TREE_SCALE;
|
||||
_voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel);
|
||||
|
||||
// delete it locally to see the effect immediately (and in case no voxel server is present)
|
||||
_voxels.getTree()->deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
}
|
||||
|
||||
|
||||
void Application::makeVoxel(glm::vec3 position,
|
||||
float scale,
|
||||
unsigned char red,
|
||||
unsigned char green,
|
||||
unsigned char blue,
|
||||
bool isDestructive) {
|
||||
VoxelDetail voxel;
|
||||
voxel.x = position.x / TREE_SCALE;
|
||||
voxel.y = position.y / TREE_SCALE;
|
||||
voxel.z = position.z / TREE_SCALE;
|
||||
voxel.s = scale / TREE_SCALE;
|
||||
voxel.red = red;
|
||||
voxel.green = green;
|
||||
voxel.blue = blue;
|
||||
PacketType message = isDestructive ? PacketTypeVoxelSetDestructive : PacketTypeVoxelSet;
|
||||
_voxelEditSender.sendVoxelEditMessage(message, voxel);
|
||||
|
||||
// create the voxel locally so it appears immediately
|
||||
_voxels.getTree()->createVoxel(voxel.x, voxel.y, voxel.z, voxel.s,
|
||||
voxel.red, voxel.green, voxel.blue,
|
||||
isDestructive);
|
||||
}
|
||||
|
||||
glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel) {
|
||||
return glm::vec3((mouseVoxel.x + mouseVoxel.s / 2.0f) * TREE_SCALE, (mouseVoxel.y + mouseVoxel.s / 2.0f) * TREE_SCALE,
|
||||
(mouseVoxel.z + mouseVoxel.s / 2.0f) * TREE_SCALE);
|
||||
}
|
||||
|
||||
bool Application::mouseOnScreen() const {
|
||||
if (OculusManager::isConnected()) {
|
||||
GLCanvas::SharedPointer glCanvas = DependencyManager::get<GLCanvas>();
|
||||
|
@ -1702,10 +1606,6 @@ FaceTracker* Application::getActiveFaceTracker() {
|
|||
(visage->isActive() ? static_cast<FaceTracker*>(visage.data()) : NULL)));
|
||||
}
|
||||
|
||||
struct SendVoxelsOperationArgs {
|
||||
const unsigned char* newBaseOctCode;
|
||||
};
|
||||
|
||||
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
|
||||
QVector<EntityItem*> entities;
|
||||
_entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE,
|
||||
|
@ -1732,88 +1632,6 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Application::sendVoxelsOperation(OctreeElement* element, void* extraData) {
|
||||
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
|
||||
SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData;
|
||||
if (voxel->isColored()) {
|
||||
const unsigned char* nodeOctalCode = voxel->getOctalCode();
|
||||
unsigned char* codeColorBuffer = NULL;
|
||||
int codeLength = 0;
|
||||
int bytesInCode = 0;
|
||||
int codeAndColorLength;
|
||||
|
||||
// If the newBase is NULL, then don't rebase
|
||||
if (args->newBaseOctCode) {
|
||||
codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true);
|
||||
codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer);
|
||||
bytesInCode = bytesRequiredForCodeLength(codeLength);
|
||||
codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA;
|
||||
} else {
|
||||
codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode);
|
||||
bytesInCode = bytesRequiredForCodeLength(codeLength);
|
||||
codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA;
|
||||
codeColorBuffer = new unsigned char[codeAndColorLength];
|
||||
memcpy(codeColorBuffer, nodeOctalCode, bytesInCode);
|
||||
}
|
||||
|
||||
// copy the colors over
|
||||
codeColorBuffer[bytesInCode + RED_INDEX] = voxel->getColor()[RED_INDEX];
|
||||
codeColorBuffer[bytesInCode + GREEN_INDEX] = voxel->getColor()[GREEN_INDEX];
|
||||
codeColorBuffer[bytesInCode + BLUE_INDEX] = voxel->getColor()[BLUE_INDEX];
|
||||
getInstance()->_voxelEditSender.queueVoxelEditMessage(PacketTypeVoxelSetDestructive,
|
||||
codeColorBuffer, codeAndColorLength);
|
||||
|
||||
delete[] codeColorBuffer;
|
||||
}
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
void Application::exportVoxels(const VoxelDetail& sourceVoxel) {
|
||||
QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
QString suggestedName = desktopLocation.append("/voxels.svo");
|
||||
|
||||
QString fileNameString = QFileDialog::getSaveFileName(DependencyManager::get<GLCanvas>().data(),
|
||||
tr("Export Voxels"), suggestedName,
|
||||
tr("Sparse Voxel Octree Files (*.svo)"));
|
||||
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
|
||||
const char* fileName = fileNameAscii.data();
|
||||
|
||||
VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
if (selectedNode) {
|
||||
VoxelTree exportTree;
|
||||
getVoxelTree()->copySubTreeIntoNewTree(selectedNode, &exportTree, true);
|
||||
exportTree.writeToSVOFile(fileName);
|
||||
}
|
||||
|
||||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
}
|
||||
|
||||
void Application::importVoxels() {
|
||||
_importSucceded = false;
|
||||
|
||||
if (!_voxelImportDialog) {
|
||||
_voxelImportDialog = new VoxelImportDialog(_window);
|
||||
_voxelImportDialog->loadSettings(_settings);
|
||||
}
|
||||
|
||||
if (!_voxelImportDialog->exec()) {
|
||||
qDebug() << "Import succeeded." << endl;
|
||||
_importSucceded = true;
|
||||
} else {
|
||||
qDebug() << "Import failed." << endl;
|
||||
if (_sharedVoxelSystem.getTree() == _voxelImporter.getVoxelTree()) {
|
||||
_sharedVoxelSystem.killLocalVoxels();
|
||||
_sharedVoxelSystem.changeTree(&_clipboard);
|
||||
}
|
||||
}
|
||||
|
||||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
|
||||
emit importDone();
|
||||
}
|
||||
|
||||
bool Application::importEntities(const QString& filename) {
|
||||
_entityClipboard.eraseAllOctreeElements();
|
||||
bool success = _entityClipboard.readFromSVOFile(filename.toLocal8Bit().constData());
|
||||
|
@ -1827,71 +1645,6 @@ void Application::pasteEntities(float x, float y, float z) {
|
|||
_entityClipboard.sendEntities(&_entityEditSender, _entities.getTree(), x, y, z);
|
||||
}
|
||||
|
||||
void Application::cutVoxels(const VoxelDetail& sourceVoxel) {
|
||||
copyVoxels(sourceVoxel);
|
||||
deleteVoxelAt(sourceVoxel);
|
||||
}
|
||||
|
||||
void Application::copyVoxels(const VoxelDetail& sourceVoxel) {
|
||||
// switch to and clear the clipboard first...
|
||||
_sharedVoxelSystem.killLocalVoxels();
|
||||
if (_sharedVoxelSystem.getTree() != &_clipboard) {
|
||||
_clipboard.eraseAllOctreeElements();
|
||||
_sharedVoxelSystem.changeTree(&_clipboard);
|
||||
}
|
||||
|
||||
// then copy onto it if there is something to copy
|
||||
VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
if (selectedNode) {
|
||||
getVoxelTree()->copySubTreeIntoNewTree(selectedNode, _sharedVoxelSystem.getTree(), true);
|
||||
_sharedVoxelSystem.forceRedrawEntireTree();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination) {
|
||||
// Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to
|
||||
// the server as an set voxel message, this will also rebase the voxels to the new location
|
||||
SendVoxelsOperationArgs args;
|
||||
args.newBaseOctCode = octalCodeDestination;
|
||||
_sharedVoxelSystem.getTree()->recurseTreeWithOperation(sendVoxelsOperation, &args);
|
||||
|
||||
// Switch back to clipboard if it was an import
|
||||
if (_sharedVoxelSystem.getTree() != &_clipboard) {
|
||||
_sharedVoxelSystem.killLocalVoxels();
|
||||
_sharedVoxelSystem.changeTree(&_clipboard);
|
||||
}
|
||||
|
||||
_voxelEditSender.releaseQueuedMessages();
|
||||
}
|
||||
|
||||
void Application::pasteVoxels(const VoxelDetail& sourceVoxel) {
|
||||
unsigned char* calculatedOctCode = NULL;
|
||||
VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
|
||||
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
||||
// voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a
|
||||
// target octalCode for where the user is pointing.
|
||||
const unsigned char* octalCodeDestination;
|
||||
if (selectedNode) {
|
||||
octalCodeDestination = selectedNode->getOctalCode();
|
||||
} else {
|
||||
octalCodeDestination = calculatedOctCode = pointToVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
}
|
||||
|
||||
pasteVoxelsToOctalCode(octalCodeDestination);
|
||||
|
||||
if (calculatedOctCode) {
|
||||
delete[] calculatedOctCode;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) {
|
||||
VoxelTreeElement* nodeToNudge = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
if (nodeToNudge) {
|
||||
_voxels.getTree()->nudgeSubTree(nodeToNudge, nudgeVec, _voxelEditSender);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::initDisplay() {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
|
@ -1902,23 +1655,6 @@ void Application::initDisplay() {
|
|||
}
|
||||
|
||||
void Application::init() {
|
||||
_sharedVoxelSystemViewFrustum.setPosition(glm::vec3(TREE_SCALE / 2.0f,
|
||||
TREE_SCALE / 2.0f,
|
||||
3.0f * TREE_SCALE / 2.0f));
|
||||
_sharedVoxelSystemViewFrustum.setNearClip(TREE_SCALE / 2.0f);
|
||||
_sharedVoxelSystemViewFrustum.setFarClip(3.0f * TREE_SCALE / 2.0f);
|
||||
_sharedVoxelSystemViewFrustum.setFieldOfView(90.0f);
|
||||
_sharedVoxelSystemViewFrustum.setOrientation(glm::quat());
|
||||
_sharedVoxelSystemViewFrustum.calculate();
|
||||
_sharedVoxelSystem.setViewFrustum(&_sharedVoxelSystemViewFrustum);
|
||||
|
||||
VoxelTreeElement::removeUpdateHook(&_sharedVoxelSystem);
|
||||
|
||||
// Cleanup of the original shared tree
|
||||
_sharedVoxelSystem.init();
|
||||
|
||||
_voxelImportDialog = new VoxelImportDialog(_window);
|
||||
|
||||
_environment.init();
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->init(this);
|
||||
|
@ -1991,29 +1727,18 @@ void Application::init() {
|
|||
// fire off an immediate domain-server check in now that settings are loaded
|
||||
NodeList::getInstance()->sendDomainServerCheckIn();
|
||||
|
||||
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
|
||||
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
|
||||
_voxels.setDisableFastVoxelPipeline(false);
|
||||
_voxels.init();
|
||||
|
||||
_entities.init();
|
||||
_entities.setViewFrustum(getViewFrustum());
|
||||
|
||||
EntityTree* entityTree = _entities.getTree();
|
||||
_entityCollisionSystem.init(&_entityEditSender, entityTree, _voxels.getTree(), &_audio, &_avatarManager);
|
||||
_entityCollisionSystem.init(&_entityEditSender, entityTree, &_audio, &_avatarManager);
|
||||
entityTree->setSimulation(&_entityCollisionSystem);
|
||||
|
||||
// connect the _entityCollisionSystem to our script engine's EntityScriptingInterface
|
||||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel,
|
||||
ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithVoxel);
|
||||
|
||||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
|
||||
ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity);
|
||||
|
||||
// connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts
|
||||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel,
|
||||
&_entities, &EntityTreeRenderer::entityCollisionWithVoxel);
|
||||
|
||||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
|
||||
&_entities, &EntityTreeRenderer::entityCollisionWithEntity);
|
||||
|
||||
|
@ -2226,10 +1951,8 @@ void Application::updateThreads(float deltaTime) {
|
|||
PerformanceWarning warn(showWarnings, "Application::updateThreads()");
|
||||
|
||||
// parse voxel packets
|
||||
if (!_enableProcessVoxelsThread) {
|
||||
if (!_enableProcessOctreeThread) {
|
||||
_octreeProcessor.threadRoutine();
|
||||
_voxelHideShowThread.threadRoutine();
|
||||
_voxelEditSender.threadRoutine();
|
||||
_entityEditSender.threadRoutine();
|
||||
}
|
||||
}
|
||||
|
@ -2416,9 +2139,6 @@ void Application::update(float deltaTime) {
|
|||
if (queryIsDue || viewIsDifferentEnough) {
|
||||
_lastQueriedTime = now;
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||
queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) {
|
||||
queryOctree(NodeType::EntityServer, PacketTypeEntityQuery, _entityServerJurisdictions);
|
||||
}
|
||||
|
@ -2476,8 +2196,7 @@ int Application::sendNackPackets() {
|
|||
|
||||
nodeList->eachNode([&](const SharedNodePointer& node){
|
||||
|
||||
if (node->getActiveSocket()
|
||||
&& (node->getType() == NodeType::VoxelServer || node->getType() == NodeType::EntityServer)) {
|
||||
if (node->getActiveSocket() && node->getType() == NodeType::EntityServer) {
|
||||
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
|
||||
|
@ -2561,7 +2280,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
|
||||
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
|
||||
_octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition());
|
||||
_octreeQuery.setOctreeSizeScale(Menu::getInstance()->getVoxelSizeScale());
|
||||
_octreeQuery.setOctreeSizeScale(Menu::getInstance()->getOctreeSizeScale());
|
||||
_octreeQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust());
|
||||
|
||||
unsigned char queryPacket[MAX_PACKET_SIZE];
|
||||
|
@ -2614,7 +2333,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
int perServerPPS = 0;
|
||||
const int SMALL_BUDGET = 10;
|
||||
int perUnknownServer = SMALL_BUDGET;
|
||||
int totalPPS = Menu::getInstance()->getMaxVoxelPacketsPerSecond();
|
||||
int totalPPS = Menu::getInstance()->getMaxOctreePacketsPerSecond();
|
||||
|
||||
// determine PPS based on number of servers
|
||||
if (inViewServers >= 1) {
|
||||
|
@ -2717,7 +2436,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||
|
||||
// Feed number of bytes to corresponding channel of the bandwidth meter
|
||||
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength);
|
||||
_bandwidthMeter.outputStream(BandwidthMeter::OCTREE).updateValue(packetLength);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -2962,7 +2681,7 @@ bool Application::shouldRenderMesh(float largestDimension, float distanceToCamer
|
|||
}
|
||||
|
||||
float Application::getSizeScale() const {
|
||||
return Menu::getInstance()->getVoxelSizeScale();
|
||||
return Menu::getInstance()->getOctreeSizeScale();
|
||||
}
|
||||
|
||||
int Application::getBoundaryLevelAdjust() const {
|
||||
|
@ -3119,14 +2838,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr
|
|||
glColor3f(1,0,0);
|
||||
DependencyManager::get<GeometryCache>()->renderSphere(originSphereRadius, 15, 15);
|
||||
|
||||
// Draw voxels
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||
PerformanceTimer perfTimer("voxels");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::displaySide() ... voxels...");
|
||||
_voxels.render();
|
||||
}
|
||||
|
||||
// also, metavoxels
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) {
|
||||
PerformanceTimer perfTimer("metavoxels");
|
||||
|
@ -3203,21 +2914,21 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr
|
|||
renderViewFrustum(_viewFrustum);
|
||||
}
|
||||
|
||||
// render voxel fades if they exist
|
||||
if (_voxelFades.size() > 0) {
|
||||
PerformanceTimer perfTimer("voxelFades");
|
||||
// render octree fades if they exist
|
||||
if (_octreeFades.size() > 0) {
|
||||
PerformanceTimer perfTimer("octreeFades");
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::displaySide() ... voxel fades...");
|
||||
_voxelFadesLock.lockForWrite();
|
||||
for(std::vector<VoxelFade>::iterator fade = _voxelFades.begin(); fade != _voxelFades.end();) {
|
||||
"Application::displaySide() ... octree fades...");
|
||||
_octreeFadesLock.lockForWrite();
|
||||
for(std::vector<OctreeFade>::iterator fade = _octreeFades.begin(); fade != _octreeFades.end();) {
|
||||
fade->render();
|
||||
if(fade->isDone()) {
|
||||
fade = _voxelFades.erase(fade);
|
||||
fade = _octreeFades.erase(fade);
|
||||
} else {
|
||||
++fade;
|
||||
}
|
||||
}
|
||||
_voxelFadesLock.unlock();
|
||||
_octreeFadesLock.unlock();
|
||||
}
|
||||
|
||||
// give external parties a change to hook in
|
||||
|
@ -3590,20 +3301,6 @@ void Application::renderViewFrustum(ViewFrustum& viewFrustum) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::deleteVoxels(const VoxelDetail& voxel) {
|
||||
deleteVoxelAt(voxel);
|
||||
}
|
||||
|
||||
void Application::deleteVoxelAt(const VoxelDetail& voxel) {
|
||||
if (voxel.s != 0) {
|
||||
// sending delete to the server is sufficient, server will send new version so we see updates soon enough
|
||||
_voxelEditSender.sendVoxelEditMessage(PacketTypeVoxelErase, voxel);
|
||||
|
||||
// delete it locally to see the effect immediately (and in case no voxel server is present)
|
||||
_voxels.getTree()->deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::resetSensors() {
|
||||
DependencyManager::get<Faceshift>()->reset();
|
||||
DependencyManager::get<Visage>()->reset();
|
||||
|
@ -3694,10 +3391,6 @@ void Application::clearDomainOctreeDetails() {
|
|||
_environment.resetToDefault();
|
||||
|
||||
// reset our node to stats and node to jurisdiction maps... since these must be changing...
|
||||
_voxelServerJurisdictions.lockForWrite();
|
||||
_voxelServerJurisdictions.clear();
|
||||
_voxelServerJurisdictions.unlock();
|
||||
|
||||
_entityServerJurisdictions.lockForWrite();
|
||||
_entityServerJurisdictions.clear();
|
||||
_entityServerJurisdictions.unlock();
|
||||
|
@ -3709,8 +3402,6 @@ void Application::clearDomainOctreeDetails() {
|
|||
// reset the model renderer
|
||||
_entities.clear();
|
||||
|
||||
// reset the voxels renderer
|
||||
_voxels.killLocalVoxels();
|
||||
}
|
||||
|
||||
void Application::domainChanged(const QString& domainHostname) {
|
||||
|
@ -3747,51 +3438,13 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
|
||||
_octreeProcessor.nodeKilled(node);
|
||||
|
||||
_voxelEditSender.nodeKilled(node);
|
||||
_entityEditSender.nodeKilled(node);
|
||||
|
||||
if (node->getType() == NodeType::AudioMixer) {
|
||||
QMetaObject::invokeMethod(&_audio, "audioMixerKilled");
|
||||
}
|
||||
|
||||
if (node->getType() == NodeType::VoxelServer) {
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
// see if this is the first we've heard of this node...
|
||||
_voxelServerJurisdictions.lockForRead();
|
||||
if (_voxelServerJurisdictions.find(nodeUUID) != _voxelServerJurisdictions.end()) {
|
||||
unsigned char* rootCode = _voxelServerJurisdictions[nodeUUID].getRootOctalCode();
|
||||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
_voxelServerJurisdictions.unlock();
|
||||
|
||||
qDebug("voxel server going away...... v[%f, %f, %f, %f]",
|
||||
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||
|
||||
// Add the jurisditionDetails object to the list of "fade outs"
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) {
|
||||
VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE);
|
||||
fade.voxelDetails = rootDetails;
|
||||
const float slightly_smaller = 0.99f;
|
||||
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
||||
_voxelFadesLock.lockForWrite();
|
||||
_voxelFades.push_back(fade);
|
||||
_voxelFadesLock.unlock();
|
||||
}
|
||||
|
||||
// If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
|
||||
_voxelServerJurisdictions.lockForWrite();
|
||||
_voxelServerJurisdictions.erase(_voxelServerJurisdictions.find(nodeUUID));
|
||||
}
|
||||
_voxelServerJurisdictions.unlock();
|
||||
|
||||
// also clean up scene stats for that server
|
||||
_octreeSceneStatsLock.lockForWrite();
|
||||
if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) {
|
||||
_octreeServerSceneStats.erase(nodeUUID);
|
||||
}
|
||||
_octreeSceneStatsLock.unlock();
|
||||
|
||||
} else if (node->getType() == NodeType::EntityServer) {
|
||||
if (node->getType() == NodeType::EntityServer) {
|
||||
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
// see if this is the first we've heard of this node...
|
||||
|
@ -3806,14 +3459,14 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||
|
||||
// Add the jurisditionDetails object to the list of "fade outs"
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) {
|
||||
VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE);
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnOctreeServerChanges)) {
|
||||
OctreeFade fade(OctreeFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE);
|
||||
fade.voxelDetails = rootDetails;
|
||||
const float slightly_smaller = 0.99f;
|
||||
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
||||
_voxelFadesLock.lockForWrite();
|
||||
_voxelFades.push_back(fade);
|
||||
_voxelFadesLock.unlock();
|
||||
_octreeFadesLock.lockForWrite();
|
||||
_octreeFades.push_back(fade);
|
||||
_octreeFadesLock.unlock();
|
||||
}
|
||||
|
||||
// If the model server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
|
||||
|
@ -3835,7 +3488,7 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket) {
|
||||
void Application::trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket) {
|
||||
|
||||
// Attempt to identify the sender from it's address.
|
||||
if (sendingNode) {
|
||||
|
@ -3879,10 +3532,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin
|
|||
// see if this is the first we've heard of this node...
|
||||
NodeToJurisdictionMap* jurisdiction = NULL;
|
||||
QString serverType;
|
||||
if (sendingNode->getType() == NodeType::VoxelServer) {
|
||||
jurisdiction = &_voxelServerJurisdictions;
|
||||
serverType = "Voxel";
|
||||
} else {
|
||||
if (sendingNode->getType() == NodeType::EntityServer) {
|
||||
jurisdiction = &_entityServerJurisdictions;
|
||||
serverType = "Entity";
|
||||
}
|
||||
|
@ -3895,14 +3545,14 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin
|
|||
qPrintable(serverType), rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||
|
||||
// Add the jurisditionDetails object to the list of "fade outs"
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) {
|
||||
VoxelFade fade(VoxelFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE);
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnOctreeServerChanges)) {
|
||||
OctreeFade fade(OctreeFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE);
|
||||
fade.voxelDetails = rootDetails;
|
||||
const float slightly_smaller = 0.99f;
|
||||
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
||||
_voxelFadesLock.lockForWrite();
|
||||
_voxelFades.push_back(fade);
|
||||
_voxelFadesLock.unlock();
|
||||
_octreeFadesLock.lockForWrite();
|
||||
_octreeFades.push_back(fade);
|
||||
_octreeFadesLock.unlock();
|
||||
}
|
||||
} else {
|
||||
jurisdiction->unlock();
|
||||
|
@ -3921,7 +3571,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin
|
|||
}
|
||||
|
||||
void Application::packetSent(quint64 length) {
|
||||
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(length);
|
||||
_bandwidthMeter.outputStream(BandwidthMeter::OCTREE).updateValue(length);
|
||||
}
|
||||
|
||||
void Application::loadScripts() {
|
||||
|
@ -3976,9 +3626,6 @@ void joystickFromScriptValue(const QScriptValue &object, Joystick* &out) {
|
|||
void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) {
|
||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||
// we can use the same ones from the application.
|
||||
scriptEngine->getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender);
|
||||
scriptEngine->getVoxelsScriptingInterface()->setVoxelTree(_voxels.getTree());
|
||||
scriptEngine->getVoxelsScriptingInterface()->setUndoStack(&_undoStack);
|
||||
scriptEngine->getEntityScriptingInterface()->setPacketSender(&_entityEditSender);
|
||||
scriptEngine->getEntityScriptingInterface()->setEntityTree(_entities.getTree());
|
||||
|
||||
|
@ -4259,10 +3906,6 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject
|
|||
|
||||
qDebug() << "Voxel costs are" << satoshisPerVoxel << "per voxel and" << satoshisPerMeterCubed << "per meter cubed";
|
||||
qDebug() << "Destination wallet UUID for voxel payments is" << voxelWalletUUID;
|
||||
|
||||
_voxelEditSender.setSatoshisPerVoxel(satoshisPerVoxel);
|
||||
_voxelEditSender.setSatoshisPerMeterCubed(satoshisPerMeterCubed);
|
||||
_voxelEditSender.setDestinationWalletUUID(voxelWalletUUID);
|
||||
}
|
||||
|
||||
QString Application::getPreviousScriptLocation() {
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <ScriptEngine.h>
|
||||
#include <TextureCache.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <VoxelEditPacketSender.h>
|
||||
|
||||
#include "Audio.h"
|
||||
#include "Camera.h"
|
||||
|
@ -70,12 +69,8 @@
|
|||
#include "ui/ApplicationOverlay.h"
|
||||
#include "ui/RunningScriptsWidget.h"
|
||||
#include "ui/ToolWindow.h"
|
||||
#include "ui/VoxelImportDialog.h"
|
||||
#include "voxels/VoxelFade.h"
|
||||
#include "voxels/VoxelHideShowThread.h"
|
||||
#include "voxels/VoxelImporter.h"
|
||||
#include "voxels/OctreePacketProcessor.h"
|
||||
#include "voxels/VoxelSystem.h"
|
||||
#include "octree/OctreeFade.h"
|
||||
#include "octree/OctreePacketProcessor.h"
|
||||
|
||||
|
||||
#include "UndoStackScriptingInterface.h"
|
||||
|
@ -125,7 +120,6 @@ class Application : public QApplication, public AbstractViewStateInterface, Abst
|
|||
Q_OBJECT
|
||||
|
||||
friend class OctreePacketProcessor;
|
||||
friend class VoxelEditPacketSender;
|
||||
friend class DatagramProcessor;
|
||||
|
||||
public:
|
||||
|
@ -166,16 +160,6 @@ public:
|
|||
bool event(QEvent* event);
|
||||
bool eventFilter(QObject* object, QEvent* event);
|
||||
|
||||
void makeVoxel(glm::vec3 position,
|
||||
float scale,
|
||||
unsigned char red,
|
||||
unsigned char green,
|
||||
unsigned char blue,
|
||||
bool isDestructive);
|
||||
|
||||
void removeVoxel(glm::vec3 position, float scale);
|
||||
|
||||
glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel);
|
||||
bool isThrottleRendering() const { return DependencyManager::get<GLCanvas>()->isThrottleRendering(); }
|
||||
|
||||
MyAvatar* getAvatar() { return _myAvatar; }
|
||||
|
@ -185,22 +169,16 @@ public:
|
|||
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
||||
ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; }
|
||||
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
|
||||
VoxelSystem* getVoxels() { return &_voxels; }
|
||||
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
||||
MetavoxelSystem* getMetavoxels() { return &_metavoxels; }
|
||||
EntityTreeRenderer* getEntities() { return &_entities; }
|
||||
VoxelSystem* getSharedVoxelSystem() { return &_sharedVoxelSystem; }
|
||||
Environment* getEnvironment() { return &_environment; }
|
||||
PrioVR* getPrioVR() { return &_prioVR; }
|
||||
QUndoStack* getUndoStack() { return &_undoStack; }
|
||||
MainWindow* getWindow() { return _window; }
|
||||
|
||||
VoxelImporter* getVoxelImporter() { return &_voxelImporter; }
|
||||
VoxelTree* getClipboard() { return &_clipboard; }
|
||||
EntityTree* getEntityClipboard() { return &_entityClipboard; }
|
||||
EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; }
|
||||
VoxelTree* getVoxelTree() { return _voxels.getTree(); }
|
||||
bool getImportSucceded() { return _importSucceded; }
|
||||
|
||||
bool isMousePressed() const { return _mousePressed; }
|
||||
bool isMouseHidden() const { return DependencyManager::get<GLCanvas>()->cursor().shape() == Qt::BlankCursor; }
|
||||
|
@ -295,9 +273,7 @@ public:
|
|||
|
||||
glm::vec2 getViewportDimensions() const { return glm::vec2(DependencyManager::get<GLCanvas>()->getDeviceWidth(),
|
||||
DependencyManager::get<GLCanvas>()->getDeviceHeight()); }
|
||||
NodeToJurisdictionMap& getVoxelServerJurisdictions() { return _voxelServerJurisdictions; }
|
||||
NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; }
|
||||
void pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination);
|
||||
|
||||
void skipVersion(QString latestVersion);
|
||||
|
||||
|
@ -347,17 +323,7 @@ public slots:
|
|||
bool exportEntities(const QString& filename, float x, float y, float z, float scale);
|
||||
bool importEntities(const QString& filename);
|
||||
|
||||
void importVoxels(); // doesn't include source voxel because it goes to clipboard
|
||||
void cutVoxels(const VoxelDetail& sourceVoxel);
|
||||
void copyVoxels(const VoxelDetail& sourceVoxel);
|
||||
void pasteVoxels(const VoxelDetail& sourceVoxel);
|
||||
void deleteVoxels(const VoxelDetail& sourceVoxel);
|
||||
void exportVoxels(const VoxelDetail& sourceVoxel);
|
||||
void nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec);
|
||||
|
||||
void setRenderVoxels(bool renderVoxels);
|
||||
void setLowVelocityFilter(bool lowVelocityFilter);
|
||||
void doKillLocalVoxels();
|
||||
void loadDialog();
|
||||
void loadScriptURLDialog();
|
||||
void toggleLogDialog();
|
||||
|
@ -420,7 +386,6 @@ private:
|
|||
void updateProjectionMatrix();
|
||||
void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true);
|
||||
|
||||
static bool sendVoxelsOperation(OctreeElement* node, void* extraData);
|
||||
void sendPingPackets();
|
||||
|
||||
void initDisplay();
|
||||
|
@ -454,12 +419,7 @@ private:
|
|||
void updateShadowMap();
|
||||
void renderRearViewMirror(const QRect& region, bool billboard = false);
|
||||
void renderViewFrustum(ViewFrustum& viewFrustum);
|
||||
|
||||
void checkBandwidthMeterClick();
|
||||
|
||||
void deleteVoxelAt(const VoxelDetail& voxel);
|
||||
void eyedropperVoxelUnderCursor();
|
||||
|
||||
void setMenuShortcutsEnabled(bool enabled);
|
||||
|
||||
static void attachNewHeadToNode(Node *newNode);
|
||||
|
@ -495,14 +455,6 @@ private:
|
|||
bool _justStarted;
|
||||
Stars _stars;
|
||||
|
||||
VoxelSystem _voxels;
|
||||
VoxelTree _clipboard; // if I copy/paste
|
||||
VoxelImportDialog* _voxelImportDialog;
|
||||
VoxelImporter _voxelImporter;
|
||||
bool _importSucceded;
|
||||
VoxelSystem _sharedVoxelSystem;
|
||||
ViewFrustum _sharedVoxelSystemViewFrustum;
|
||||
|
||||
#ifdef USE_BULLET_PHYSICS
|
||||
PhysicsEngine _physicsEngine;
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
|
@ -512,9 +464,6 @@ private:
|
|||
EntityTreeRenderer _entityClipboardRenderer;
|
||||
EntityTree _entityClipboard;
|
||||
|
||||
QByteArray _voxelsFilename;
|
||||
bool _wantToKillLocalVoxels;
|
||||
|
||||
MetavoxelSystem _metavoxels;
|
||||
|
||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||
|
@ -525,7 +474,7 @@ private:
|
|||
|
||||
float _trailingAudioLoudness;
|
||||
|
||||
OctreeQuery _octreeQuery; // NodeData derived class for querying voxels from voxel server
|
||||
OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers
|
||||
|
||||
AvatarManager _avatarManager;
|
||||
MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be)
|
||||
|
@ -573,10 +522,8 @@ private:
|
|||
|
||||
Audio _audio;
|
||||
|
||||
bool _enableProcessVoxelsThread;
|
||||
bool _enableProcessOctreeThread;
|
||||
OctreePacketProcessor _octreeProcessor;
|
||||
VoxelHideShowThread _voxelHideShowThread;
|
||||
VoxelEditPacketSender _voxelEditSender;
|
||||
EntityEditPacketSender _entityEditSender;
|
||||
|
||||
int _packetsPerSecond;
|
||||
|
@ -586,17 +533,16 @@ private:
|
|||
float _idleLoopMeasuredJitter;
|
||||
|
||||
int parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sendingNode);
|
||||
void trackIncomingVoxelPacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket);
|
||||
void trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket);
|
||||
|
||||
NodeToJurisdictionMap _voxelServerJurisdictions;
|
||||
NodeToJurisdictionMap _entityServerJurisdictions;
|
||||
NodeToOctreeSceneStats _octreeServerSceneStats;
|
||||
QReadWriteLock _octreeSceneStatsLock;
|
||||
|
||||
NodeBounds _nodeBoundsDisplay;
|
||||
|
||||
std::vector<VoxelFade> _voxelFades;
|
||||
QReadWriteLock _voxelFadesLock;
|
||||
std::vector<OctreeFade> _octreeFades;
|
||||
QReadWriteLock _octreeFadesLock;
|
||||
ControllerScriptingInterface _controllerScriptingInterface;
|
||||
QPointer<LogDialog> _logDialog;
|
||||
QPointer<SnapshotShareDialog> _snapshotShareDialog;
|
||||
|
|
|
@ -125,7 +125,7 @@ Audio::Audio(QObject* parent) :
|
|||
_lastSentAudioPacket(0),
|
||||
_outputBufferSizeFrames(DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES),
|
||||
_packetSentTimeGaps(1, APPROXIMATELY_30_SECONDS_OF_AUDIO_PACKETS),
|
||||
_audioOutputIODevice(_receivedAudioStream)
|
||||
_audioOutputIODevice(_receivedAudioStream, this)
|
||||
{
|
||||
// clear the array of locally injected samples
|
||||
memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
|
||||
|
@ -1825,6 +1825,16 @@ bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
|
|||
return supportedFormat;
|
||||
}
|
||||
|
||||
void Audio::outputNotify() {
|
||||
int recentUnfulfilled = _audioOutputIODevice.getRecentUnfulfilledReads();
|
||||
if (recentUnfulfilled > 0) {
|
||||
qDebug() << "WARNING --- WE HAD at least:" << recentUnfulfilled << "recently unfulfilled readData() calls";
|
||||
|
||||
// TODO: Ryan Huffman -- add code here to increase the AUDIO_OUTPUT_BUFFER_SIZE_FRAMES... this code only
|
||||
// runs in cases where the audio device requested data samples, and ran dry because we couldn't fulfill the request
|
||||
}
|
||||
}
|
||||
|
||||
bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) {
|
||||
bool supportedFormat = false;
|
||||
|
||||
|
@ -1857,6 +1867,9 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo)
|
|||
// setup our general output device for audio-mixer audio
|
||||
_audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
_audioOutput->setBufferSize(_outputBufferSizeFrames * _outputFrameSize * sizeof(int16_t));
|
||||
|
||||
connect(_audioOutput, &QAudioOutput::notify, this, &Audio::outputNotify);
|
||||
|
||||
qDebug() << "Output Buffer capacity in frames: " << _audioOutput->bufferSize() / sizeof(int16_t) / (float)_outputFrameSize;
|
||||
|
||||
_audioOutputIODevice.start();
|
||||
|
@ -1949,6 +1962,7 @@ qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
|||
int samplesRequested = maxSize / sizeof(int16_t);
|
||||
int samplesPopped;
|
||||
int bytesWritten;
|
||||
|
||||
if ((samplesPopped = _receivedAudioStream.popSamples(samplesRequested, false)) > 0) {
|
||||
AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput();
|
||||
lastPopOutput.readSamples((int16_t*)data, samplesPopped);
|
||||
|
@ -1958,5 +1972,10 @@ qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
|||
bytesWritten = maxSize;
|
||||
}
|
||||
|
||||
int bytesAudioOutputUnplayed = _audio->_audioOutput->bufferSize() - _audio->_audioOutput->bytesFree();
|
||||
if (bytesAudioOutputUnplayed == 0 && bytesWritten == 0) {
|
||||
_unfulfilledReads++;
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
|
|
@ -75,16 +75,22 @@ public:
|
|||
|
||||
class AudioOutputIODevice : public QIODevice {
|
||||
public:
|
||||
AudioOutputIODevice(MixedProcessedAudioStream& receivedAudioStream) : _receivedAudioStream(receivedAudioStream) {};
|
||||
AudioOutputIODevice(MixedProcessedAudioStream& receivedAudioStream, Audio* audio) :
|
||||
_receivedAudioStream(receivedAudioStream), _audio(audio), _unfulfilledReads(0) {};
|
||||
|
||||
void start() { open(QIODevice::ReadOnly); }
|
||||
void stop() { close(); }
|
||||
qint64 readData(char * data, qint64 maxSize);
|
||||
qint64 writeData(const char * data, qint64 maxSize) { return 0; }
|
||||
|
||||
int getRecentUnfulfilledReads() { int unfulfilledReads = _unfulfilledReads; _unfulfilledReads = 0; return unfulfilledReads; }
|
||||
private:
|
||||
MixedProcessedAudioStream& _receivedAudioStream;
|
||||
Audio* _audio;
|
||||
int _unfulfilledReads;
|
||||
};
|
||||
|
||||
friend class AudioOutputIODevice;
|
||||
|
||||
// setup for audio I/O
|
||||
Audio(QObject* parent = 0);
|
||||
|
@ -176,11 +182,15 @@ public slots:
|
|||
const AudioStreamStats& getAudioMixerAvatarStreamAudioStats() const { return _audioMixerAvatarStreamAudioStats; }
|
||||
const QHash<QUuid, AudioStreamStats>& getAudioMixerInjectedStreamAudioStatsMap() const { return _audioMixerInjectedStreamAudioStatsMap; }
|
||||
|
||||
void outputNotify();
|
||||
|
||||
signals:
|
||||
bool muteToggled();
|
||||
void preProcessOriginalInboundAudio(unsigned int sampleTime, QByteArray& samples, const QAudioFormat& format);
|
||||
void processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
|
||||
void processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
|
||||
|
||||
|
||||
private:
|
||||
void outputFormatChanged();
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include <EventTypes.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
|
|
@ -81,31 +81,15 @@ void DatagramProcessor::processDatagrams() {
|
|||
break;
|
||||
case PacketTypeEntityData:
|
||||
case PacketTypeEntityErase:
|
||||
case PacketTypeVoxelData:
|
||||
case PacketTypeVoxelErase:
|
||||
case PacketTypeOctreeStats:
|
||||
case PacketTypeEnvironmentData: {
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"Application::networkReceive()... _octreeProcessor.queueReceivedPacket()");
|
||||
bool wantExtraDebugging = application->getLogger()->extraDebugging();
|
||||
if (wantExtraDebugging && packetTypeForPacket(incomingPacket) == PacketTypeVoxelData) {
|
||||
int numBytesPacketHeader = numBytesForPacketHeader(incomingPacket);
|
||||
unsigned char* dataAt = reinterpret_cast<unsigned char*>(incomingPacket.data()) + numBytesPacketHeader;
|
||||
dataAt += sizeof(OCTREE_PACKET_FLAGS);
|
||||
OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt);
|
||||
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
|
||||
OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt);
|
||||
dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
|
||||
OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
|
||||
int flightTime = arrivedAt - sentAt;
|
||||
|
||||
qDebug("got an Octree data or erase message, sequence:%d flightTime:%d", sequence, flightTime);
|
||||
}
|
||||
|
||||
|
||||
SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket);
|
||||
|
||||
if (matchedNode) {
|
||||
// add this packet to our list of voxel packets and process them on the voxel processing
|
||||
// add this packet to our list of octree packets and process them on the octree data processing
|
||||
application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket);
|
||||
}
|
||||
|
||||
|
@ -167,11 +151,6 @@ void DatagramProcessor::processDatagrams() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PacketTypeVoxelEditNack:
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
|
||||
application->_voxelEditSender.processNackPacket(incomingPacket);
|
||||
}
|
||||
break;
|
||||
case PacketTypeEntityEditNack:
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
|
||||
application->_entityEditSender.processNackPacket(incomingPacket);
|
||||
|
|
|
@ -72,6 +72,7 @@ void Environment::renderAtmospheres(Camera& camera) {
|
|||
QMutexLocker locker(&_mutex);
|
||||
|
||||
foreach (const ServerData& serverData, _data) {
|
||||
// TODO: do something about EnvironmentData
|
||||
foreach (const EnvironmentData& environmentData, serverData) {
|
||||
renderAtmosphere(camera, environmentData);
|
||||
}
|
||||
|
|
|
@ -109,8 +109,7 @@ Menu::Menu() :
|
|||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
_speechRecognizer(),
|
||||
#endif
|
||||
_maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM),
|
||||
_voxelSizeScale(DEFAULT_OCTREE_SIZE_SCALE),
|
||||
_octreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE),
|
||||
_oculusUIAngularSize(DEFAULT_OCULUS_UI_ANGULAR_SIZE),
|
||||
_sixenseReticleMoveSpeed(DEFAULT_SIXENSE_RETICLE_MOVE_SPEED),
|
||||
_invertSixenseButtons(DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS),
|
||||
|
@ -119,7 +118,7 @@ Menu::Menu() :
|
|||
_avatarLODIncreaseFPS(ADJUST_LOD_UP_FPS),
|
||||
_avatarLODDistanceMultiplier(DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER),
|
||||
_boundaryLevelAdjust(0),
|
||||
_maxVoxelPacketsPerSecond(DEFAULT_MAX_VOXEL_PPS),
|
||||
_maxOctreePacketsPerSecond(DEFAULT_MAX_OCTREE_PPS),
|
||||
_lastAdjust(usecTimestampNow()),
|
||||
_lastAvatarDetailDrop(usecTimestampNow()),
|
||||
_fpsAverage(FIVE_SECONDS_OF_FRAMES),
|
||||
|
@ -316,8 +315,6 @@ Menu::Menu() :
|
|||
avatar, SLOT(onToggleRagdoll()));
|
||||
addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithAvatars,
|
||||
0, true, avatar, SLOT(updateCollisionGroups()));
|
||||
addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithVoxels,
|
||||
0, false, avatar, SLOT(updateCollisionGroups()));
|
||||
addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideWithEnvironment,
|
||||
0, false, avatar, SLOT(updateCollisionGroups()));
|
||||
|
||||
|
@ -391,6 +388,9 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Avatars, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Entities, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DontFadeOnOctreeServerChanges);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DisableAutoAdjustLOD);
|
||||
|
||||
QMenu* shadowMenu = renderOptionsMenu->addMenu("Shadows");
|
||||
QActionGroup* shadowGroup = new QActionGroup(shadowMenu);
|
||||
|
@ -425,12 +425,6 @@ Menu::Menu() :
|
|||
resolutionGroup->addAction(addCheckableActionToQMenuAndActionHash(resolutionMenu, MenuOption::RenderResolutionQuarter, 0, false));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, Qt::Key_Asterisk, true);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu,
|
||||
MenuOption::Voxels,
|
||||
Qt::SHIFT | Qt::Key_V,
|
||||
true,
|
||||
appInstance,
|
||||
SLOT(setRenderVoxels(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableGlowEffect, 0, true,
|
||||
DependencyManager::get<GlowEffect>().data(), SLOT(toggleGlowEffect(bool)));
|
||||
|
||||
|
@ -457,12 +451,6 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false);
|
||||
|
||||
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels");
|
||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
|
||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
|
||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges);
|
||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DisableAutoAdjustLOD);
|
||||
|
||||
QMenu* metavoxelOptionsMenu = developerMenu->addMenu("Metavoxels");
|
||||
addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false,
|
||||
Application::getInstance()->getMetavoxels(), SLOT(refreshVoxelData()));
|
||||
|
@ -636,11 +624,6 @@ Menu::Menu() :
|
|||
|
||||
connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
|
||||
|
||||
addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_V,
|
||||
this,
|
||||
SLOT(pasteToVoxel()));
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
QMenu* helpMenu = addMenu("Help");
|
||||
QAction* helpAction = helpMenu->addAction(MenuOption::AboutApp);
|
||||
|
@ -681,9 +664,8 @@ void Menu::loadSettings(QSettings* settings) {
|
|||
_realWorldFieldOfView = loadSetting(settings, "realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES);
|
||||
_faceshiftEyeDeflection = loadSetting(settings, "faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION);
|
||||
_faceshiftHostname = settings->value("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME).toString();
|
||||
_maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM);
|
||||
_maxVoxelPacketsPerSecond = loadSetting(settings, "maxVoxelsPPS", DEFAULT_MAX_VOXEL_PPS);
|
||||
_voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_OCTREE_SIZE_SCALE);
|
||||
_maxOctreePacketsPerSecond = loadSetting(settings, "maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
|
||||
_octreeSizeScale = loadSetting(settings, "octreeSizeScale", DEFAULT_OCTREE_SIZE_SCALE);
|
||||
_automaticAvatarLOD = settings->value("automaticAvatarLOD", true).toBool();
|
||||
_avatarLODDecreaseFPS = loadSetting(settings, "avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS);
|
||||
_avatarLODIncreaseFPS = loadSetting(settings, "avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS);
|
||||
|
@ -750,9 +732,8 @@ void Menu::saveSettings(QSettings* settings) {
|
|||
settings->setValue("fieldOfView", _fieldOfView);
|
||||
settings->setValue("faceshiftEyeDeflection", _faceshiftEyeDeflection);
|
||||
settings->setValue("faceshiftHostname", _faceshiftHostname);
|
||||
settings->setValue("maxVoxels", _maxVoxels);
|
||||
settings->setValue("maxVoxelsPPS", _maxVoxelPacketsPerSecond);
|
||||
settings->setValue("voxelSizeScale", _voxelSizeScale);
|
||||
settings->setValue("maxOctreePPS", _maxOctreePacketsPerSecond);
|
||||
settings->setValue("octreeSizeScale", _octreeSizeScale);
|
||||
settings->setValue("automaticAvatarLOD", _automaticAvatarLOD);
|
||||
settings->setValue("avatarLODDecreaseFPS", _avatarLODDecreaseFPS);
|
||||
settings->setValue("avatarLODIncreaseFPS", _avatarLODIncreaseFPS);
|
||||
|
@ -1266,33 +1247,6 @@ void Menu::nameLocation() {
|
|||
_newLocationDialog->showNormal();
|
||||
}
|
||||
|
||||
void Menu::pasteToVoxel() {
|
||||
QInputDialog pasteToOctalCodeDialog(Application::getInstance()->getWindow());
|
||||
pasteToOctalCodeDialog.setWindowTitle("Paste to Voxel");
|
||||
pasteToOctalCodeDialog.setLabelText("Octal Code:");
|
||||
QString octalCode = "";
|
||||
pasteToOctalCodeDialog.setTextValue(octalCode);
|
||||
pasteToOctalCodeDialog.setWindowFlags(Qt::Sheet);
|
||||
pasteToOctalCodeDialog.resize(pasteToOctalCodeDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW,
|
||||
pasteToOctalCodeDialog.size().height());
|
||||
|
||||
int dialogReturn = pasteToOctalCodeDialog.exec();
|
||||
if (dialogReturn == QDialog::Accepted && !pasteToOctalCodeDialog.textValue().isEmpty()) {
|
||||
// we got an octalCode to paste to...
|
||||
QString locationToPaste = pasteToOctalCodeDialog.textValue();
|
||||
unsigned char* octalCodeDestination = hexStringToOctalCode(locationToPaste);
|
||||
|
||||
// check to see if it was a legit octcode...
|
||||
if (locationToPaste == octalCodeToHexString(octalCodeDestination)) {
|
||||
Application::getInstance()->pasteVoxelsToOctalCode(octalCodeDestination);
|
||||
} else {
|
||||
qDebug() << "Problem with octcode...";
|
||||
}
|
||||
}
|
||||
|
||||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
void Menu::toggleLoginMenuItem() {
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
|
||||
|
@ -1462,8 +1416,8 @@ QString Menu::getLODFeedbackText() {
|
|||
}
|
||||
|
||||
// distance feedback
|
||||
float voxelSizeScale = getVoxelSizeScale();
|
||||
float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
|
||||
float octreeSizeScale = getOctreeSizeScale();
|
||||
float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
|
||||
QString result;
|
||||
if (relativeToDefault > 1.01) {
|
||||
result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback);
|
||||
|
@ -1514,29 +1468,29 @@ void Menu::autoAdjustLOD(float currentFPS) {
|
|||
quint64 elapsed = now - _lastAdjust;
|
||||
|
||||
if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS
|
||||
&& _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
|
||||
&& _octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
|
||||
|
||||
_voxelSizeScale *= ADJUST_LOD_DOWN_BY;
|
||||
_octreeSizeScale *= ADJUST_LOD_DOWN_BY;
|
||||
|
||||
if (_voxelSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
|
||||
_voxelSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
|
||||
if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
|
||||
_octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
|
||||
}
|
||||
changed = true;
|
||||
_lastAdjust = now;
|
||||
qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
||||
<< "_voxelSizeScale=" << _voxelSizeScale;
|
||||
<< "_octreeSizeScale=" << _octreeSizeScale;
|
||||
}
|
||||
|
||||
if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
|
||||
&& _voxelSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
|
||||
_voxelSizeScale *= ADJUST_LOD_UP_BY;
|
||||
if (_voxelSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
|
||||
_voxelSizeScale = ADJUST_LOD_MAX_SIZE_SCALE;
|
||||
&& _octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
|
||||
_octreeSizeScale *= ADJUST_LOD_UP_BY;
|
||||
if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
|
||||
_octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE;
|
||||
}
|
||||
changed = true;
|
||||
_lastAdjust = now;
|
||||
qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
||||
<< "_voxelSizeScale=" << _voxelSizeScale;
|
||||
<< "_octreeSizeScale=" << _octreeSizeScale;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
|
@ -1553,8 +1507,8 @@ void Menu::resetLODAdjust() {
|
|||
_lastAvatarDetailDrop = _lastAdjust = usecTimestampNow();
|
||||
}
|
||||
|
||||
void Menu::setVoxelSizeScale(float sizeScale) {
|
||||
_voxelSizeScale = sizeScale;
|
||||
void Menu::setOctreeSizeScale(float sizeScale) {
|
||||
_octreeSizeScale = sizeScale;
|
||||
_shouldRenderTableNeedsRebuilding = true;
|
||||
bumpSettings();
|
||||
}
|
||||
|
@ -1565,14 +1519,14 @@ void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
|
|||
bumpSettings();
|
||||
}
|
||||
|
||||
// TODO: This is essentially the same logic used to render voxels, but since models are more detailed then voxels
|
||||
// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells
|
||||
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
|
||||
bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) {
|
||||
const float voxelToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
|
||||
float voxelSizeScale = getVoxelSizeScale();
|
||||
const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
|
||||
float octreeSizeScale = getOctreeSizeScale();
|
||||
int boundaryLevelAdjust = getBoundaryLevelAdjust();
|
||||
float maxScale = (float)TREE_SCALE;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, voxelSizeScale) / voxelToMeshRatio;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio;
|
||||
|
||||
if (_shouldRenderTableNeedsRebuilding) {
|
||||
_shouldRenderTable.clear();
|
||||
|
|
|
@ -122,7 +122,6 @@ public:
|
|||
OctreeStatsDialog* getOctreeStatsDialog() const { return _octreeStatsDialog; }
|
||||
LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; }
|
||||
HMDToolsDialog* getHMDToolsDialog() const { return _hmdToolsDialog; }
|
||||
int getMaxVoxels() const { return _maxVoxels; }
|
||||
|
||||
bool getShadowsEnabled() const;
|
||||
|
||||
|
@ -132,8 +131,8 @@ public:
|
|||
QString getLODFeedbackText();
|
||||
void autoAdjustLOD(float currentFPS);
|
||||
void resetLODAdjust();
|
||||
void setVoxelSizeScale(float sizeScale);
|
||||
float getVoxelSizeScale() const { return _voxelSizeScale; }
|
||||
void setOctreeSizeScale(float sizeScale);
|
||||
float getOctreeSizeScale() const { return _octreeSizeScale; }
|
||||
void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; bumpSettings(); }
|
||||
bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; }
|
||||
void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; bumpSettings(); }
|
||||
|
@ -152,8 +151,8 @@ public:
|
|||
#endif
|
||||
|
||||
// User Tweakable PPS from Voxel Server
|
||||
int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPacketsPerSecond; }
|
||||
void setMaxVoxelPacketsPerSecond(int maxVoxelPacketsPerSecond) { _maxVoxelPacketsPerSecond = maxVoxelPacketsPerSecond; bumpSettings(); }
|
||||
int getMaxOctreePacketsPerSecond() const { return _maxOctreePacketsPerSecond; }
|
||||
void setMaxOctreePacketsPerSecond(int value) { _maxOctreePacketsPerSecond = value; bumpSettings(); }
|
||||
|
||||
QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString& actionName,
|
||||
|
@ -190,7 +189,6 @@ public slots:
|
|||
void importSettings();
|
||||
void exportSettings();
|
||||
void toggleAddressBar();
|
||||
void pasteToVoxel();
|
||||
|
||||
void toggleLoginMenuItem();
|
||||
void toggleSixense(bool shouldEnable);
|
||||
|
@ -293,8 +291,7 @@ private:
|
|||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
SpeechRecognizer _speechRecognizer;
|
||||
#endif
|
||||
int _maxVoxels;
|
||||
float _voxelSizeScale;
|
||||
float _octreeSizeScale;
|
||||
float _oculusUIAngularSize;
|
||||
float _sixenseReticleMoveSpeed;
|
||||
bool _invertSixenseButtons;
|
||||
|
@ -303,7 +300,7 @@ private:
|
|||
float _avatarLODIncreaseFPS;
|
||||
float _avatarLODDistanceMultiplier;
|
||||
int _boundaryLevelAdjust;
|
||||
int _maxVoxelPacketsPerSecond;
|
||||
int _maxOctreePacketsPerSecond;
|
||||
QString replaceLastOccurrence(QChar search, QChar replace, QString string);
|
||||
quint64 _lastAdjust;
|
||||
quint64 _lastAvatarDetailDrop;
|
||||
|
@ -357,14 +354,12 @@ namespace MenuOption {
|
|||
const QString CollideAsRagdoll = "Collide With Self (Ragdoll)";
|
||||
const QString CollideWithAvatars = "Collide With Other Avatars";
|
||||
const QString CollideWithEnvironment = "Collide With World Boundaries";
|
||||
const QString CollideWithVoxels = "Collide With Voxels";
|
||||
const QString Collisions = "Collisions";
|
||||
const QString Console = "Console...";
|
||||
const QString ControlWithSpeech = "Control With Speech";
|
||||
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
|
||||
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
|
||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||
const QString DecreaseVoxelSize = "Decrease Voxel Size";
|
||||
const QString DisableActivityLogger = "Disable Activity Logger";
|
||||
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
|
||||
const QString DisableLightEntities = "Disable Light Entities";
|
||||
|
@ -378,7 +373,7 @@ namespace MenuOption {
|
|||
const QString DisplayModelElementChildProxies = "Display Model Element Children";
|
||||
const QString DisplayModelElementProxy = "Display Model Element Bounds";
|
||||
const QString DisplayTimingDetails = "Display Timing Details";
|
||||
const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes";
|
||||
const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes";
|
||||
const QString EchoLocalAudio = "Echo Local Audio";
|
||||
const QString EchoServerAudio = "Echo Server Audio";
|
||||
const QString EditEntitiesHelp = "Edit Entities Help...";
|
||||
|
@ -404,7 +399,6 @@ namespace MenuOption {
|
|||
const QString HeadMouse = "Head Mouse";
|
||||
const QString HMDTools = "HMD Tools";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IncreaseVoxelSize = "Increase Voxel Size";
|
||||
const QString KeyboardMotorControl = "Enable Keyboard Motor Control";
|
||||
const QString LeapMotionOnHMD = "Leap Motion on HMD";
|
||||
const QString LoadScript = "Open and Run Script File...";
|
||||
|
@ -428,7 +422,6 @@ namespace MenuOption {
|
|||
const QString OffAxisProjection = "Off-Axis Projection";
|
||||
const QString OldVoxelCullingMode = "Old Voxel Culling Mode";
|
||||
const QString Pair = "Pair";
|
||||
const QString PasteToVoxel = "Paste to Voxel...";
|
||||
const QString PipelineWarnings = "Log Render Pipeline Warnings";
|
||||
const QString Preferences = "Preferences...";
|
||||
const QString Quit = "Quit";
|
||||
|
@ -486,9 +479,6 @@ namespace MenuOption {
|
|||
const QString UploadSkeleton = "Upload Skeleton Model";
|
||||
const QString UserInterface = "User Interface";
|
||||
const QString Visage = "Visage";
|
||||
const QString VoxelMode = "Cycle Voxel Mode";
|
||||
const QString Voxels = "Voxels";
|
||||
const QString VoxelTextures = "Voxel Textures";
|
||||
const QString WalletPrivateKey = "Wallet Private Key...";
|
||||
const QString Wireframe = "Wireframe";
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <TextRenderer.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "VoxelConstants.h"
|
||||
#include "world.h"
|
||||
#include "Application.h"
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "ModelReferential.h"
|
||||
#include "Physics.h"
|
||||
#include "Recorder.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
#include "devices/OculusManager.h"
|
||||
|
||||
|
@ -1042,9 +1043,6 @@ void Avatar::updateCollisionGroups() {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) {
|
||||
_collisionGroups |= COLLISION_GROUP_AVATARS;
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) {
|
||||
_collisionGroups |= COLLISION_GROUP_VOXELS;
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::setScale(float scale) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <HeadData.h>
|
||||
|
||||
#include <VoxelConstants.h>
|
||||
#include <OctreeConstants.h> // for IDENTITY_*
|
||||
|
||||
#include "FaceModel.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "Recorder.h"
|
||||
#include "devices/Faceshift.h"
|
||||
#include "devices/OculusManager.h"
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -1459,20 +1460,6 @@ static CollisionList myCollisions(64);
|
|||
|
||||
void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) {
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
if (_voxelShapeManager.needsUpdate(now)) {
|
||||
// We use a multiple of the avatar's boundingRadius as the size of the cube of interest.
|
||||
float cubeScale = 6.0f * getBoundingRadius();
|
||||
glm::vec3 corner = getPosition() - glm::vec3(0.5f * cubeScale);
|
||||
AACube boundingCube(corner, cubeScale);
|
||||
|
||||
// query the VoxelTree for cubes that touch avatar's boundingCube
|
||||
CubeList cubes;
|
||||
if (Application::getInstance()->getVoxelTree()->findContentInCube(boundingCube, cubes)) {
|
||||
_voxelShapeManager.updateVoxels(now, cubes);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Andrew to do ground/walking detection in ragdoll mode
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) {
|
||||
const float MAX_VOXEL_COLLISION_SPEED = 100.0f;
|
||||
|
@ -1937,8 +1924,7 @@ void MyAvatar::updateMotionBehavior() {
|
|||
if (menu->isOptionChecked(MenuOption::StandOnNearbyFloors)) {
|
||||
_motionBehaviors |= AVATAR_MOTION_STAND_ON_NEARBY_FLOORS;
|
||||
// standing on floors requires collision with voxels
|
||||
_collisionGroups |= COLLISION_GROUP_VOXELS;
|
||||
menu->setIsOptionChecked(MenuOption::CollideWithVoxels, true);
|
||||
// TODO: determine what to do with this now that voxels are gone
|
||||
} else {
|
||||
_motionBehaviors &= ~AVATAR_MOTION_STAND_ON_NEARBY_FLOORS;
|
||||
}
|
||||
|
@ -1991,7 +1977,8 @@ void MyAvatar::setCollisionGroups(quint32 collisionGroups) {
|
|||
Menu* menu = Menu::getInstance();
|
||||
menu->setIsOptionChecked(MenuOption::CollideWithEnvironment, (bool)(_collisionGroups & COLLISION_GROUP_ENVIRONMENT));
|
||||
menu->setIsOptionChecked(MenuOption::CollideWithAvatars, (bool)(_collisionGroups & COLLISION_GROUP_AVATARS));
|
||||
menu->setIsOptionChecked(MenuOption::CollideWithVoxels, (bool)(_collisionGroups & COLLISION_GROUP_VOXELS));
|
||||
|
||||
// TODO: what to do about this now that voxels are gone
|
||||
if (! (_collisionGroups & COLLISION_GROUP_VOXELS)) {
|
||||
// no collision with voxels --> disable standing on floors
|
||||
_motionBehaviors &= ~AVATAR_MOTION_STAND_ON_NEARBY_FLOORS;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Menu.h"
|
||||
#include "SkeletonModel.h"
|
||||
#include "SkeletonRagdoll.h"
|
||||
#include "Util.h"
|
||||
|
||||
enum StandingFootState {
|
||||
LEFT_FOOT,
|
||||
|
|
|
@ -146,11 +146,6 @@ void SixenseManager::update(float deltaTime) {
|
|||
#ifdef HAVE_SIXENSE
|
||||
Hand* hand = Application::getInstance()->getAvatar()->getHand();
|
||||
if (_isInitialized && _isEnabled) {
|
||||
// Disable the hands (and return to default pose) if both controllers are at base station
|
||||
for (std::vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
|
||||
it->setActive(!_controllersAtBase);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
SixenseBaseFunction sixenseGetNumActiveControllers =
|
||||
(SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers");
|
||||
|
@ -213,6 +208,14 @@ void SixenseManager::update(float deltaTime) {
|
|||
qDebug("Found new Sixense controller, ID %i", data->controller_index);
|
||||
}
|
||||
|
||||
// Disable the hands (and return to default pose) if both controllers are at base station
|
||||
if (foundHand) {
|
||||
palm->setActive(!_controllersAtBase);
|
||||
} else {
|
||||
palm->setActive(false); // if this isn't a Sixsense ID palm, always make it inactive
|
||||
}
|
||||
|
||||
|
||||
// Read controller buttons and joystick into the hand
|
||||
palm->setControllerButtons(data->buttons);
|
||||
palm->setTrigger(data->trigger);
|
||||
|
@ -508,7 +511,6 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
|
|||
QMouseEvent mouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton, 0);
|
||||
|
||||
//Only send the mouse event if the opposite left button isnt held down.
|
||||
//This is specifically for edit voxels
|
||||
if (triggerButton == Qt::LeftButton) {
|
||||
if (!_triggerPressed[(int)(!index)]) {
|
||||
application->mouseMoveEvent(&mouseEvent, deviceID);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// VoxelFade.cpp
|
||||
// OctreeFade.cpp
|
||||
// interface/src/voxels
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/13.
|
||||
|
@ -13,22 +13,22 @@
|
|||
|
||||
#include <GlowEffect.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include <OctreeConstants.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "VoxelFade.h"
|
||||
#include "OctreeFade.h"
|
||||
|
||||
const float VoxelFade::FADE_OUT_START = 0.5f;
|
||||
const float VoxelFade::FADE_OUT_END = 0.05f;
|
||||
const float VoxelFade::FADE_OUT_STEP = 0.9f;
|
||||
const float VoxelFade::FADE_IN_START = 0.05f;
|
||||
const float VoxelFade::FADE_IN_END = 0.5f;
|
||||
const float VoxelFade::FADE_IN_STEP = 1.1f;
|
||||
const float VoxelFade::DEFAULT_RED = 0.5f;
|
||||
const float VoxelFade::DEFAULT_GREEN = 0.5f;
|
||||
const float VoxelFade::DEFAULT_BLUE = 0.5f;
|
||||
const float OctreeFade::FADE_OUT_START = 0.5f;
|
||||
const float OctreeFade::FADE_OUT_END = 0.05f;
|
||||
const float OctreeFade::FADE_OUT_STEP = 0.9f;
|
||||
const float OctreeFade::FADE_IN_START = 0.05f;
|
||||
const float OctreeFade::FADE_IN_END = 0.5f;
|
||||
const float OctreeFade::FADE_IN_STEP = 1.1f;
|
||||
const float OctreeFade::DEFAULT_RED = 0.5f;
|
||||
const float OctreeFade::DEFAULT_GREEN = 0.5f;
|
||||
const float OctreeFade::DEFAULT_BLUE = 0.5f;
|
||||
|
||||
VoxelFade::VoxelFade(FadeDirection direction, float red, float green, float blue) :
|
||||
OctreeFade::OctreeFade(FadeDirection direction, float red, float green, float blue) :
|
||||
direction(direction),
|
||||
red(red),
|
||||
green(green),
|
||||
|
@ -37,7 +37,7 @@ VoxelFade::VoxelFade(FadeDirection direction, float red, float green, float blue
|
|||
opacity = (direction == FADE_OUT) ? FADE_OUT_START : FADE_IN_START;
|
||||
}
|
||||
|
||||
void VoxelFade::render() {
|
||||
void OctreeFade::render() {
|
||||
DependencyManager::get<GlowEffect>()->begin();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
@ -59,7 +59,7 @@ void VoxelFade::render() {
|
|||
opacity *= (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP;
|
||||
}
|
||||
|
||||
bool VoxelFade::isDone() const {
|
||||
bool OctreeFade::isDone() const {
|
||||
if (direction == FADE_OUT) {
|
||||
return opacity <= FADE_OUT_END;
|
||||
} else {
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// VoxelFade.h
|
||||
// OctreeFade.h
|
||||
// interface/src/voxels
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/13.
|
||||
|
@ -9,12 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_VoxelFade_h
|
||||
#define hifi_VoxelFade_h
|
||||
#ifndef hifi_OctreeFade_h
|
||||
#define hifi_OctreeFade_h
|
||||
|
||||
#include <OctalCode.h> // for VoxelPositionSize
|
||||
|
||||
class VoxelFade {
|
||||
class OctreeFade {
|
||||
public:
|
||||
|
||||
enum FadeDirection { FADE_OUT, FADE_IN};
|
||||
|
@ -36,11 +36,11 @@ public:
|
|||
float green;
|
||||
float blue;
|
||||
|
||||
VoxelFade(FadeDirection direction = FADE_OUT, float red = DEFAULT_RED,
|
||||
OctreeFade(FadeDirection direction = FADE_OUT, float red = DEFAULT_RED,
|
||||
float green = DEFAULT_GREEN, float blue = DEFAULT_BLUE);
|
||||
|
||||
void render();
|
||||
bool isDone() const;
|
||||
};
|
||||
|
||||
#endif // hifi_VoxelFade_h
|
||||
#endif // hifi_OctreeFade_h
|
|
@ -32,12 +32,6 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode,
|
|||
bool wasStatsPacket = false;
|
||||
|
||||
|
||||
// check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that
|
||||
if (app->_wantToKillLocalVoxels) {
|
||||
app->_voxels.killLocalVoxels();
|
||||
app->_wantToKillLocalVoxels = false;
|
||||
}
|
||||
|
||||
PacketType voxelPacketType = packetTypeForPacket(mutablePacket);
|
||||
|
||||
// note: PacketType_OCTREE_STATS can have PacketType_VOXEL_DATA
|
||||
|
@ -80,7 +74,7 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode,
|
|||
}
|
||||
|
||||
|
||||
app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket);
|
||||
app->trackIncomingOctreePacket(mutablePacket, sendingNode, wasStatsPacket);
|
||||
|
||||
if (sendingNode) {
|
||||
|
||||
|
@ -101,12 +95,8 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode,
|
|||
app->_environment.parseData(*sendingNode->getActiveSocket(), mutablePacket);
|
||||
} break;
|
||||
|
||||
default : {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||
app->_voxels.setDataSourceUUID(sendingNode->getUUID());
|
||||
app->_voxels.parseData(mutablePacket);
|
||||
app->_voxels.setDataSourceUUID(QUuid());
|
||||
}
|
||||
default: {
|
||||
// nothing to do
|
||||
} break;
|
||||
}
|
||||
}
|
|
@ -15,124 +15,6 @@ ClipboardScriptingInterface::ClipboardScriptingInterface() {
|
|||
connect(this, SIGNAL(readyToImport()), Application::getInstance(), SLOT(importVoxels()));
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::cutVoxel(const VoxelDetail& sourceVoxel) {
|
||||
cutVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::cutVoxel(float x, float y, float z, float s) {
|
||||
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
s / (float)TREE_SCALE };
|
||||
Application::getInstance()->cutVoxels(sourceVoxel);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::copyVoxel(const VoxelDetail& sourceVoxel) {
|
||||
copyVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::copyVoxel(float x, float y, float z, float s) {
|
||||
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
s / (float)TREE_SCALE };
|
||||
Application::getInstance()->copyVoxels(sourceVoxel);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::pasteVoxel(const VoxelDetail& destinationVoxel) {
|
||||
pasteVoxel(destinationVoxel.x, destinationVoxel.y, destinationVoxel.z, destinationVoxel.s);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::pasteVoxel(float x, float y, float z, float s) {
|
||||
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
s / (float)TREE_SCALE };
|
||||
|
||||
Application::getInstance()->pasteVoxels(sourceVoxel);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::deleteVoxel(const VoxelDetail& sourceVoxel) {
|
||||
deleteVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::deleteVoxel(float x, float y, float z, float s) {
|
||||
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
s / (float)TREE_SCALE };
|
||||
Application::getInstance()->deleteVoxels(sourceVoxel);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::exportVoxel(const VoxelDetail& sourceVoxel) {
|
||||
exportVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::exportVoxel(float x, float y, float z, float s) {
|
||||
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
s / (float)TREE_SCALE };
|
||||
|
||||
Application::getInstance()->exportVoxels(sourceVoxel);
|
||||
}
|
||||
|
||||
bool ClipboardScriptingInterface::importVoxels() {
|
||||
qDebug() << "Importing ... ";
|
||||
QEventLoop loop;
|
||||
connect(Application::getInstance(), SIGNAL(importDone()), &loop, SLOT(quit()));
|
||||
emit readyToImport();
|
||||
loop.exec();
|
||||
|
||||
return Application::getInstance()->getImportSucceded();
|
||||
}
|
||||
|
||||
bool ClipboardScriptingInterface::importVoxels(const QString& filename) {
|
||||
qDebug() << "Importing ... ";
|
||||
|
||||
VoxelImporter* importer = Application::getInstance()->getVoxelImporter();
|
||||
|
||||
if (!importer->validImportFile(filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QEventLoop loop;
|
||||
connect(importer, SIGNAL(importDone()), &loop, SLOT(quit()));
|
||||
importer->import(filename);
|
||||
loop.exec();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClipboardScriptingInterface::importVoxels(const QString& filename, float x, float y, float z, float s) {
|
||||
bool success = importVoxels(filename);
|
||||
|
||||
if (success) {
|
||||
pasteVoxel(x, y, z, s);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ClipboardScriptingInterface::importVoxels(const QString& filename, const VoxelDetail& destinationVoxel) {
|
||||
return importVoxels(filename, destinationVoxel.x, destinationVoxel.y, destinationVoxel.z, destinationVoxel.s);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) {
|
||||
nudgeVoxel(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s, nudgeVec);
|
||||
}
|
||||
|
||||
void ClipboardScriptingInterface::nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec) {
|
||||
glm::vec3 nudgeVecInTreeSpace = nudgeVec / (float)TREE_SCALE;
|
||||
VoxelDetail sourceVoxel = { x / (float)TREE_SCALE,
|
||||
y / (float)TREE_SCALE,
|
||||
z / (float)TREE_SCALE,
|
||||
s / (float)TREE_SCALE };
|
||||
|
||||
Application::getInstance()->nudgeVoxelsByVector(sourceVoxel, nudgeVecInTreeSpace);
|
||||
}
|
||||
|
||||
|
||||
bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) {
|
||||
return Application::getInstance()->exportEntities(filename, x, y, z, s);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#define hifi_ClipboardScriptingInterface_h
|
||||
|
||||
#include <QObject>
|
||||
#include <VoxelDetail.h>
|
||||
|
||||
class ClipboardScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -23,29 +22,6 @@ signals:
|
|||
void readyToImport();
|
||||
|
||||
public slots:
|
||||
void cutVoxel(const VoxelDetail& sourceVoxel);
|
||||
void cutVoxel(float x, float y, float z, float s);
|
||||
|
||||
void copyVoxel(const VoxelDetail& sourceVoxel);
|
||||
void copyVoxel(float x, float y, float z, float s);
|
||||
|
||||
void pasteVoxel(const VoxelDetail& destinationVoxel);
|
||||
void pasteVoxel(float x, float y, float z, float s);
|
||||
|
||||
void deleteVoxel(const VoxelDetail& sourceVoxel);
|
||||
void deleteVoxel(float x, float y, float z, float s);
|
||||
|
||||
void exportVoxel(const VoxelDetail& sourceVoxel);
|
||||
void exportVoxel(float x, float y, float z, float s);
|
||||
|
||||
bool importVoxels();
|
||||
bool importVoxels(const QString& filename);
|
||||
bool importVoxels(const QString& filename, float x, float y, float z, float s);
|
||||
bool importVoxels(const QString& filename, const VoxelDetail& destinationVoxel);
|
||||
|
||||
void nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec);
|
||||
void nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec);
|
||||
|
||||
bool importEntities(const QString& filename);
|
||||
bool exportEntities(const QString& filename, float x, float y, float z, float s);
|
||||
void pasteEntities(float x, float y, float z, float s);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "ApplicationOverlay.h"
|
||||
#include "devices/OculusManager.h"
|
||||
|
||||
#include "Util.h"
|
||||
#include "ui/Stats.h"
|
||||
|
||||
// Used to fade the UI
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace { // .cpp-local
|
|||
BandwidthMeter::ChannelInfo BandwidthMeter::_CHANNELS[] = {
|
||||
{ "Audio" , "Kbps", 8000.0 / 1024.0, 0x33cc99ff },
|
||||
{ "Avatars" , "Kbps", 8000.0 / 1024.0, 0xffef40c0 },
|
||||
{ "Voxels" , "Kbps", 8000.0 / 1024.0, 0xd0d0d0a0 },
|
||||
{ "Octree" , "Kbps", 8000.0 / 1024.0, 0xd0d0d0a0 },
|
||||
{ "Metavoxels", "Kbps", 8000.0 / 1024.0, 0xd0d0d0a0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
static size_t const N_STREAMS = N_CHANNELS * 2;
|
||||
|
||||
// Channel usage.
|
||||
enum ChannelIndex { AUDIO, AVATARS, VOXELS, METAVOXELS };
|
||||
enum ChannelIndex { AUDIO, AVATARS, OCTREE, METAVOXELS };
|
||||
|
||||
// Meta information held for a communication channel (bidirectional).
|
||||
struct ChannelInfo {
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
#include "devices/OculusManager.h"
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#include <QPushButton>
|
||||
#include <QString>
|
||||
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
#include "Menu.h"
|
||||
#include "ui/LodToolsDialog.h"
|
||||
|
||||
|
@ -47,7 +45,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
_lodSize->setTickPosition(QSlider::TicksBelow);
|
||||
_lodSize->setFixedWidth(SLIDER_WIDTH);
|
||||
_lodSize->setPageStep(PAGE_STEP_LOD_SIZE);
|
||||
int sliderValue = Menu::getInstance()->getVoxelSizeScale() / TREE_SCALE;
|
||||
int sliderValue = Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE;
|
||||
_lodSize->setValue(sliderValue);
|
||||
form->addRow("LOD Size Scale:", _lodSize);
|
||||
connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int)));
|
||||
|
@ -116,7 +114,7 @@ LodToolsDialog::~LodToolsDialog() {
|
|||
}
|
||||
|
||||
void LodToolsDialog::reloadSliders() {
|
||||
_lodSize->setValue(Menu::getInstance()->getVoxelSizeScale() / TREE_SCALE);
|
||||
_lodSize->setValue(Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE);
|
||||
_boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust());
|
||||
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
|
||||
}
|
||||
|
@ -156,7 +154,7 @@ void LodToolsDialog::updateAvatarLODValues() {
|
|||
|
||||
void LodToolsDialog::sizeScaleValueChanged(int value) {
|
||||
float realValue = value * TREE_SCALE;
|
||||
Menu::getInstance()->setVoxelSizeScale(realValue);
|
||||
Menu::getInstance()->setOctreeSizeScale(realValue);
|
||||
|
||||
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
|
||||
}
|
||||
|
|
|
@ -148,6 +148,7 @@ MetavoxelEditor::MetavoxelEditor() :
|
|||
return;
|
||||
}
|
||||
|
||||
_gridProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/grid.vert");
|
||||
_gridProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/grid.frag");
|
||||
_gridProgram.link();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Created by Ryan Huffman on 05/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// This class draws a border around the different Voxel, Entity nodes on the current domain,
|
||||
// This class draws a border around the different Entity nodes on the current domain,
|
||||
// and a semi-transparent cube around the currently mouse-overed node.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
@ -21,19 +21,17 @@
|
|||
|
||||
NodeBounds::NodeBounds(QObject* parent) :
|
||||
QObject(parent),
|
||||
_showVoxelNodes(false),
|
||||
_showEntityNodes(false),
|
||||
_overlayText() {
|
||||
|
||||
}
|
||||
|
||||
void NodeBounds::draw() {
|
||||
if (!(_showVoxelNodes || _showEntityNodes)) {
|
||||
if (!_showEntityNodes) {
|
||||
_overlayText[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions();
|
||||
NodeToJurisdictionMap& entityServerJurisdictions = Application::getInstance()->getEntityServerJurisdictions();
|
||||
NodeToJurisdictionMap* serverJurisdictions;
|
||||
|
||||
|
@ -54,9 +52,7 @@ void NodeBounds::draw() {
|
|||
nodeList->eachNode([&](const SharedNodePointer& node){
|
||||
NodeType_t nodeType = node->getType();
|
||||
|
||||
if (nodeType == NodeType::VoxelServer && _showVoxelNodes) {
|
||||
serverJurisdictions = &voxelServerJurisdictions;
|
||||
} else if (nodeType == NodeType::EntityServer && _showEntityNodes) {
|
||||
if (nodeType == NodeType::EntityServer && _showEntityNodes) {
|
||||
serverJurisdictions = &entityServerJurisdictions;
|
||||
} else {
|
||||
return;
|
||||
|
@ -81,7 +77,6 @@ void NodeBounds::draw() {
|
|||
glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR)
|
||||
+ ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f);
|
||||
|
||||
const float VOXEL_NODE_SCALE = 1.00f;
|
||||
const float ENTITY_NODE_SCALE = 0.99f;
|
||||
|
||||
float scaleFactor = rootDetails.s * TREE_SCALE;
|
||||
|
@ -91,9 +86,7 @@ void NodeBounds::draw() {
|
|||
scaleFactor *= 0.92 + (rootDetails.s * 0.08);
|
||||
|
||||
// Scale different node types slightly differently because it's common for them to overlap.
|
||||
if (nodeType == NodeType::VoxelServer) {
|
||||
scaleFactor *= VOXEL_NODE_SCALE;
|
||||
} else if (nodeType == NodeType::EntityServer) {
|
||||
if (nodeType == NodeType::EntityServer) {
|
||||
scaleFactor *= ENTITY_NODE_SCALE;
|
||||
}
|
||||
|
||||
|
@ -205,7 +198,7 @@ void NodeBounds::drawNodeBorder(const glm::vec3& center, float scale, float red,
|
|||
}
|
||||
|
||||
void NodeBounds::getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue) {
|
||||
red = nodeType == NodeType::VoxelServer ? 1.0 : 0.0;
|
||||
red = nodeType == 0.0;
|
||||
green = 0.0;
|
||||
blue = nodeType == NodeType::EntityServer ? 1.0 : 0.0;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ class NodeBounds : public QObject {
|
|||
public:
|
||||
NodeBounds(QObject* parent = NULL);
|
||||
|
||||
bool getShowVoxelNodes() { return _showVoxelNodes; }
|
||||
bool getShowEntityNodes() { return _showEntityNodes; }
|
||||
bool getShowParticleNodes() { return _showParticleNodes; }
|
||||
|
||||
|
@ -31,7 +30,6 @@ public:
|
|||
void drawOverlay();
|
||||
|
||||
public slots:
|
||||
void setShowVoxelNodes(bool value) { _showVoxelNodes = value; }
|
||||
void setShowEntityNodes(bool value) { _showEntityNodes = value; }
|
||||
void setShowParticleNodes(bool value) { _showParticleNodes = value; }
|
||||
|
||||
|
@ -40,7 +38,6 @@ protected:
|
|||
void getColorForNodeType(NodeType_t nodeType, float& red, float& green, float& blue);
|
||||
|
||||
private:
|
||||
bool _showVoxelNodes;
|
||||
bool _showEntityNodes;
|
||||
bool _showParticleNodes;
|
||||
char _overlayText[MAX_OVERLAY_TEXT_LENGTH + 1];
|
||||
|
|
|
@ -28,10 +28,10 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo
|
|||
_model(model) {
|
||||
|
||||
_statCount = 0;
|
||||
_voxelServerLabelsCount = 0;
|
||||
_octreeServerLabelsCount = 0;
|
||||
|
||||
for (int i = 0; i < MAX_VOXEL_SERVERS; i++) {
|
||||
_voxelServerLables[i] = 0;
|
||||
_octreeServerLables[i] = 0;
|
||||
_extraServerDetails[i] = LESS;
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,9 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo
|
|||
this->QDialog::setLayout(_form);
|
||||
|
||||
// Setup stat items
|
||||
_serverVoxels = AddStatItem("Elements on Servers");
|
||||
_localVoxels = AddStatItem("Local Elements");
|
||||
_localVoxelsMemory = AddStatItem("Elements Memory");
|
||||
_voxelsRendered = AddStatItem("Voxels Rendered");
|
||||
_serverElements = AddStatItem("Elements on Servers");
|
||||
_localElements = AddStatItem("Local Elements");
|
||||
_localElementsMemory = AddStatItem("Elements Memory");
|
||||
_sendingMode = AddStatItem("Sending Mode");
|
||||
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
@ -122,35 +121,19 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) {
|
|||
|
||||
// Update labels
|
||||
|
||||
VoxelSystem* voxels = Application::getInstance()->getVoxels();
|
||||
QLabel* label;
|
||||
QLocale locale(QLocale::English);
|
||||
std::stringstream statsValue;
|
||||
statsValue.precision(4);
|
||||
|
||||
// Voxels Rendered
|
||||
label = _labels[_voxelsRendered];
|
||||
statsValue << "Max: " << voxels->getMaxVoxels() / 1000.0f << "K " <<
|
||||
"Drawn: " << voxels->getVoxelsWritten() / 1000.0f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.0f << "K " <<
|
||||
"ReadBuffer: " << voxels->getVoxelsRendered() / 1000.0f << "K " <<
|
||||
"Changed: " << voxels->getVoxelsUpdated() / 1000.0f << "K ";
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
// Voxels Memory Usage
|
||||
label = _labels[_localVoxelsMemory];
|
||||
// Octree Elements Memory Usage
|
||||
label = _labels[_localElementsMemory];
|
||||
statsValue.str("");
|
||||
statsValue <<
|
||||
"Elements RAM: " << OctreeElement::getTotalMemoryUsage() / 1000000.0f << "MB "
|
||||
"Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.0f << "MB " <<
|
||||
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.0f << "MB ";
|
||||
if (voxels->hasVoxelMemoryUsageGPU()) {
|
||||
statsValue << "GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.0f << "MB ";
|
||||
}
|
||||
statsValue << "Elements RAM: " << OctreeElement::getTotalMemoryUsage() / 1000000.0f << "MB ";
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
// Local Voxels
|
||||
label = _labels[_localVoxels];
|
||||
// Local Elements
|
||||
label = _labels[_localElements];
|
||||
unsigned long localTotal = OctreeElement::getNodeCount();
|
||||
unsigned long localInternal = OctreeElement::getInternalNodeCount();
|
||||
unsigned long localLeaves = OctreeElement::getLeafNodeCount();
|
||||
|
@ -208,11 +191,11 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) {
|
|||
label = _labels[_sendingMode];
|
||||
label->setText(sendingMode.str().c_str());
|
||||
|
||||
// Server Voxels
|
||||
// Server Elements
|
||||
QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' ');
|
||||
QString serversInternalString = locale.toString((uint)totalInternal);
|
||||
QString serversLeavesString = locale.toString((uint)totalLeaves);
|
||||
label = _labels[_serverVoxels];
|
||||
label = _labels[_serverElements];
|
||||
statsValue.str("");
|
||||
statsValue <<
|
||||
"Total: " << qPrintable(serversTotalString) << " / " <<
|
||||
|
@ -227,18 +210,16 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) {
|
|||
void OctreeStatsDialog::showAllOctreeServers() {
|
||||
int serverCount = 0;
|
||||
|
||||
showOctreeServersOfType(serverCount, NodeType::VoxelServer, "Voxel",
|
||||
Application::getInstance()->getVoxelServerJurisdictions());
|
||||
showOctreeServersOfType(serverCount, NodeType::EntityServer, "Entity",
|
||||
Application::getInstance()->getEntityServerJurisdictions());
|
||||
|
||||
if (_voxelServerLabelsCount > serverCount) {
|
||||
for (int i = serverCount; i < _voxelServerLabelsCount; i++) {
|
||||
int serverLabel = _voxelServerLables[i];
|
||||
if (_octreeServerLabelsCount > serverCount) {
|
||||
for (int i = serverCount; i < _octreeServerLabelsCount; i++) {
|
||||
int serverLabel = _octreeServerLables[i];
|
||||
RemoveStatItem(serverLabel);
|
||||
_voxelServerLables[i] = 0;
|
||||
_octreeServerLables[i] = 0;
|
||||
}
|
||||
_voxelServerLabelsCount = serverCount;
|
||||
_octreeServerLabelsCount = serverCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,14 +235,14 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
|
|||
if (node->getType() == serverType) {
|
||||
serverCount++;
|
||||
|
||||
if (serverCount > _voxelServerLabelsCount) {
|
||||
if (serverCount > _octreeServerLabelsCount) {
|
||||
char label[128] = { 0 };
|
||||
sprintf(label, "%s Server %d", serverTypeName, serverCount);
|
||||
int thisServerRow = _voxelServerLables[serverCount-1] = AddStatItem(label);
|
||||
int thisServerRow = _octreeServerLables[serverCount-1] = AddStatItem(label);
|
||||
_labels[thisServerRow]->setTextFormat(Qt::RichText);
|
||||
_labels[thisServerRow]->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
connect(_labels[thisServerRow], SIGNAL(linkActivated(const QString&)), this, SLOT(moreless(const QString&)));
|
||||
_voxelServerLabelsCount++;
|
||||
_octreeServerLabelsCount++;
|
||||
}
|
||||
|
||||
std::stringstream serverDetails("");
|
||||
|
@ -354,7 +335,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
|
|||
|
||||
serverDetails << "<br/>" << "Node UUID: " << qPrintable(nodeUUID.toString()) << " ";
|
||||
|
||||
serverDetails << "<br/>" << "Voxels: " <<
|
||||
serverDetails << "<br/>" << "Elements: " <<
|
||||
qPrintable(totalString) << " total " <<
|
||||
qPrintable(internalString) << " internal " <<
|
||||
qPrintable(leavesString) << " leaves ";
|
||||
|
@ -418,7 +399,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
|
|||
linkDetails << " " << " [<a href='most-" << serverCount << "'>most...</a>]";
|
||||
}
|
||||
serverDetails << linkDetails.str();
|
||||
_labels[_voxelServerLables[serverCount - 1]]->setText(serverDetails.str().c_str());
|
||||
_labels[_octreeServerLables[serverCount - 1]]->setText(serverDetails.str().c_str());
|
||||
} // is VOXEL_SERVER
|
||||
});
|
||||
}
|
||||
|
|
|
@ -60,12 +60,11 @@ private:
|
|||
int _statCount;
|
||||
|
||||
int _sendingMode;
|
||||
int _serverVoxels;
|
||||
int _localVoxels;
|
||||
int _localVoxelsMemory;
|
||||
int _voxelsRendered;
|
||||
int _voxelServerLables[MAX_VOXEL_SERVERS];
|
||||
int _voxelServerLabelsCount;
|
||||
int _serverElements;
|
||||
int _localElements;
|
||||
int _localElementsMemory;
|
||||
int _octreeServerLables[MAX_VOXEL_SERVERS];
|
||||
int _octreeServerLabelsCount;
|
||||
details _extraServerDetails[MAX_VOXEL_SERVERS];
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Audio.h"
|
||||
|
@ -149,9 +150,7 @@ void PreferencesDialog::loadPreferences() {
|
|||
|
||||
ui.avatarScaleSpin->setValue(myAvatar->getScale());
|
||||
|
||||
ui.maxVoxelsSpin->setValue(menuInstance->getMaxVoxels());
|
||||
|
||||
ui.maxVoxelsPPSSpin->setValue(menuInstance->getMaxVoxelPacketsPerSecond());
|
||||
ui.maxVoxelsPPSSpin->setValue(menuInstance->getMaxOctreePacketsPerSecond());
|
||||
|
||||
ui.oculusUIAngularSizeSpin->setValue(menuInstance->getOculusUIAngularSize());
|
||||
|
||||
|
@ -220,7 +219,6 @@ void PreferencesDialog::savePreferences() {
|
|||
myAvatar->setLeanScale(ui.leanScaleSpin->value());
|
||||
myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value());
|
||||
|
||||
Application::getInstance()->getVoxels()->setMaxVoxels(ui.maxVoxelsSpin->value());
|
||||
GLCanvas::SharedPointer glCanvas = DependencyManager::get<GLCanvas>();
|
||||
Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height());
|
||||
|
||||
|
@ -233,7 +231,7 @@ void PreferencesDialog::savePreferences() {
|
|||
|
||||
Menu::getInstance()->setFaceshiftHostname(ui.faceshiftHostnameEdit->text());
|
||||
|
||||
Menu::getInstance()->setMaxVoxelPacketsPerSecond(ui.maxVoxelsPPSSpin->value());
|
||||
Menu::getInstance()->setMaxOctreePacketsPerSecond(ui.maxVoxelsPPSSpin->value());
|
||||
|
||||
Menu::getInstance()->setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value());
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "ScriptEditorWidget.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QFileDialog>
|
||||
#include <QFrame>
|
||||
#include <QLayoutItem>
|
||||
#include <QMainWindow>
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "ui_scriptEditorWindow.h"
|
||||
#include "ScriptEditorWindow.h"
|
||||
#include "ScriptEditorWidget.h"
|
||||
|
|
|
@ -33,7 +33,7 @@ const int STATS_PELS_PER_LINE = 20;
|
|||
const int STATS_GENERAL_MIN_WIDTH = 165;
|
||||
const int STATS_PING_MIN_WIDTH = 190;
|
||||
const int STATS_GEO_MIN_WIDTH = 240;
|
||||
const int STATS_VOXEL_MIN_WIDTH = 410;
|
||||
const int STATS_OCTREE_MIN_WIDTH = 410;
|
||||
|
||||
Stats* Stats::getInstance() {
|
||||
static Stats stats;
|
||||
|
@ -47,7 +47,7 @@ Stats::Stats():
|
|||
_generalStatsWidth(STATS_GENERAL_MIN_WIDTH),
|
||||
_pingStatsWidth(STATS_PING_MIN_WIDTH),
|
||||
_geoStatsWidth(STATS_GEO_MIN_WIDTH),
|
||||
_voxelStatsWidth(STATS_VOXEL_MIN_WIDTH),
|
||||
_octreeStatsWidth(STATS_OCTREE_MIN_WIDTH),
|
||||
_lastHorizontalOffset(0),
|
||||
_metavoxelInternal(0),
|
||||
_metavoxelLeaves(0),
|
||||
|
@ -127,7 +127,7 @@ void Stats::resetWidth(int width, int horizontalOffset) {
|
|||
- STATS_GENERAL_MIN_WIDTH
|
||||
- (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0)
|
||||
- STATS_GEO_MIN_WIDTH
|
||||
- STATS_VOXEL_MIN_WIDTH;
|
||||
- STATS_OCTREE_MIN_WIDTH;
|
||||
|
||||
int panels = 4;
|
||||
|
||||
|
@ -139,7 +139,7 @@ void Stats::resetWidth(int width, int horizontalOffset) {
|
|||
panels = 3;
|
||||
}
|
||||
_geoStatsWidth = STATS_GEO_MIN_WIDTH;
|
||||
_voxelStatsWidth = STATS_VOXEL_MIN_WIDTH;
|
||||
_octreeStatsWidth = STATS_OCTREE_MIN_WIDTH;
|
||||
|
||||
if (extraSpace > panels) {
|
||||
_generalStatsWidth += (int) extraSpace / panels;
|
||||
|
@ -147,7 +147,7 @@ void Stats::resetWidth(int width, int horizontalOffset) {
|
|||
_pingStatsWidth += (int) extraSpace / panels;
|
||||
}
|
||||
_geoStatsWidth += (int) extraSpace / panels;
|
||||
_voxelStatsWidth += glCanvas->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
|
||||
_octreeStatsWidth += glCanvas->width() - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,7 @@ void Stats::display(
|
|||
int font = 2;
|
||||
|
||||
QLocale locale(QLocale::English);
|
||||
std::stringstream voxelStats;
|
||||
std::stringstream octreeStats;
|
||||
|
||||
if (_lastHorizontalOffset != horizontalOffset) {
|
||||
resetWidth(glCanvas->width(), horizontalOffset);
|
||||
|
@ -313,7 +313,7 @@ void Stats::display(
|
|||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth +1;
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
|
||||
int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingVoxelMax = -1;
|
||||
int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingOctreeMax = -1;
|
||||
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||
|
@ -323,22 +323,22 @@ void Stats::display(
|
|||
pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : -1;
|
||||
|
||||
// Now handle voxel servers, since there could be more than one, we average their ping times
|
||||
unsigned long totalPingVoxel = 0;
|
||||
int voxelServerCount = 0;
|
||||
unsigned long totalPingOctree = 0;
|
||||
int octreeServerCount = 0;
|
||||
|
||||
nodeList->eachNode([&totalPingVoxel, &pingVoxelMax, &voxelServerCount](const SharedNodePointer& node){
|
||||
nodeList->eachNode([&totalPingOctree, &pingOctreeMax, &octreeServerCount](const SharedNodePointer& node){
|
||||
// TODO: this should also support entities
|
||||
if (node->getType() == NodeType::VoxelServer) {
|
||||
totalPingVoxel += node->getPingMs();
|
||||
voxelServerCount++;
|
||||
if (pingVoxelMax < node->getPingMs()) {
|
||||
pingVoxelMax = node->getPingMs();
|
||||
if (node->getType() == NodeType::EntityServer) {
|
||||
totalPingOctree += node->getPingMs();
|
||||
octreeServerCount++;
|
||||
if (pingOctreeMax < node->getPingMs()) {
|
||||
pingOctreeMax = node->getPingMs();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (voxelServerCount) {
|
||||
pingVoxel = totalPingVoxel/voxelServerCount;
|
||||
if (octreeServerCount) {
|
||||
pingVoxel = totalPingOctree / octreeServerCount;
|
||||
}
|
||||
|
||||
lines = _expanded ? 4 : 3;
|
||||
|
@ -366,9 +366,9 @@ void Stats::display(
|
|||
|
||||
char voxelAvgPing[30];
|
||||
if (pingVoxel >= 0) {
|
||||
sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel);
|
||||
sprintf(voxelAvgPing, "Entities avg ping: %d", pingVoxel);
|
||||
} else {
|
||||
sprintf(voxelAvgPing, "Voxel avg ping: --");
|
||||
sprintf(voxelAvgPing, "Entities avg ping: --");
|
||||
}
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
|
@ -381,7 +381,7 @@ void Stats::display(
|
|||
if (_expanded) {
|
||||
char voxelMaxPing[30];
|
||||
if (pingVoxel >= 0) { // Average is only meaningful if pingVoxel is valid.
|
||||
sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax);
|
||||
sprintf(voxelMaxPing, "Voxel max ping: %d", pingOctreeMax);
|
||||
} else {
|
||||
sprintf(voxelMaxPing, "Voxel max ping: --");
|
||||
}
|
||||
|
@ -471,8 +471,6 @@ void Stats::display(
|
|||
verticalOffset = 0;
|
||||
horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3;
|
||||
|
||||
VoxelSystem* voxels = Application::getInstance()->getVoxels();
|
||||
|
||||
lines = _expanded ? 14 : 3;
|
||||
|
||||
drawBackground(backgroundColor, horizontalOffset, 0, glCanvas->width() - horizontalOffset,
|
||||
|
@ -481,65 +479,33 @@ void Stats::display(
|
|||
|
||||
// Model/Entity render details
|
||||
EntityTreeRenderer* entities = Application::getInstance()->getEntities();
|
||||
voxelStats.str("");
|
||||
voxelStats << "Entity Items rendered: " << entities->getItemsRendered()
|
||||
octreeStats.str("");
|
||||
octreeStats << "Entity Items rendered: " << entities->getItemsRendered()
|
||||
<< " / Out of view:" << entities->getItemsOutOfView()
|
||||
<< " / Too small:" << entities->getItemsTooSmall();
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
||||
if (_expanded) {
|
||||
voxelStats.str("");
|
||||
voxelStats << " Meshes rendered: " << entities->getMeshesRendered()
|
||||
octreeStats.str("");
|
||||
octreeStats << " Meshes rendered: " << entities->getMeshesRendered()
|
||||
<< " / Out of view:" << entities->getMeshesOutOfView()
|
||||
<< " / Too small:" << entities->getMeshesTooSmall();
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats << " Triangles: " << entities->getTrianglesRendered()
|
||||
octreeStats.str("");
|
||||
octreeStats << " Triangles: " << entities->getTrianglesRendered()
|
||||
<< " / Quads:" << entities->getQuadsRendered()
|
||||
<< " / Material Switches:" << entities->getMaterialSwitches();
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats << " Mesh Parts Rendered Opaque: " << entities->getOpaqueMeshPartsRendered()
|
||||
octreeStats.str("");
|
||||
octreeStats << " Mesh Parts Rendered Opaque: " << entities->getOpaqueMeshPartsRendered()
|
||||
<< " / Translucent:" << entities->getTranslucentMeshPartsRendered();
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats.precision(4);
|
||||
voxelStats << "Voxels Drawn: " << voxels->getVoxelsWritten() / 1000.0f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.0f << "K ";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
if (_expanded) {
|
||||
// Local Voxel Memory Usage
|
||||
voxelStats.str("");
|
||||
voxelStats << " Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.0f << "MB";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
" Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.0f << "MB / " <<
|
||||
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.0f << "MB";
|
||||
if (voxels->hasVoxelMemoryUsageGPU()) {
|
||||
voxelStats << " / GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.0f << "MB";
|
||||
}
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
// Voxel Rendering
|
||||
voxelStats.str("");
|
||||
voxelStats.precision(4);
|
||||
voxelStats << " Voxel Rendering Slots Max: " << voxels->getMaxVoxels() / 1000.0f << "K";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
||||
|
@ -590,13 +556,13 @@ void Stats::display(
|
|||
|
||||
// Incoming packets
|
||||
if (_expanded) {
|
||||
voxelStats.str("");
|
||||
octreeStats.str("");
|
||||
QString packetsString = locale.toString((int)voxelPacketsToProcess);
|
||||
QString maxString = locale.toString((int)_recentMaxPackets);
|
||||
voxelStats << "Voxel Packets to Process: " << qPrintable(packetsString)
|
||||
octreeStats << "Octree Packets to Process: " << qPrintable(packetsString)
|
||||
<< " [Recent Max: " << qPrintable(maxString) << "]";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) {
|
||||
|
@ -612,55 +578,55 @@ void Stats::display(
|
|||
}
|
||||
|
||||
QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' ');
|
||||
unsigned long localTotal = VoxelTreeElement::getNodeCount();
|
||||
unsigned long localTotal = OctreeElement::getNodeCount();
|
||||
QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' ');
|
||||
|
||||
// Server Octree Elements
|
||||
if (!_expanded) {
|
||||
voxelStats.str("");
|
||||
voxelStats << "Octree Elements Server: " << qPrintable(serversTotalString)
|
||||
octreeStats.str("");
|
||||
octreeStats << "Octree Elements Server: " << qPrintable(serversTotalString)
|
||||
<< " Local:" << qPrintable(localTotalString);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
if (_expanded) {
|
||||
voxelStats.str("");
|
||||
voxelStats << "Octree Elements -";
|
||||
octreeStats.str("");
|
||||
octreeStats << "Octree Elements -";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
||||
QString serversInternalString = locale.toString((uint)totalInternal);
|
||||
QString serversLeavesString = locale.toString((uint)totalLeaves);
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats << " Server: " << qPrintable(serversTotalString) <<
|
||||
octreeStats.str("");
|
||||
octreeStats << " Server: " << qPrintable(serversTotalString) <<
|
||||
" Internal: " << qPrintable(serversInternalString) <<
|
||||
" Leaves: " << qPrintable(serversLeavesString);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
||||
// Local Voxels
|
||||
unsigned long localInternal = VoxelTreeElement::getInternalNodeCount();
|
||||
unsigned long localLeaves = VoxelTreeElement::getLeafNodeCount();
|
||||
unsigned long localInternal = OctreeElement::getInternalNodeCount();
|
||||
unsigned long localLeaves = OctreeElement::getLeafNodeCount();
|
||||
QString localInternalString = locale.toString((uint)localInternal);
|
||||
QString localLeavesString = locale.toString((uint)localLeaves);
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats << " Local: " << qPrintable(serversTotalString) <<
|
||||
octreeStats.str("");
|
||||
octreeStats << " Local: " << qPrintable(serversTotalString) <<
|
||||
" Internal: " << qPrintable(localInternalString) <<
|
||||
" Leaves: " << qPrintable(localLeavesString) << "";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
// LOD Details
|
||||
if (_expanded) {
|
||||
voxelStats.str("");
|
||||
octreeStats.str("");
|
||||
QString displayLODDetails = Menu::getInstance()->getLODFeedbackText();
|
||||
voxelStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed());
|
||||
octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed());
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ private:
|
|||
int _generalStatsWidth;
|
||||
int _pingStatsWidth;
|
||||
int _geoStatsWidth;
|
||||
int _voxelStatsWidth;
|
||||
int _octreeStatsWidth;
|
||||
|
||||
int _lastHorizontalOffset;
|
||||
|
||||
|
|
|
@ -1,362 +0,0 @@
|
|||
//
|
||||
// VoxelImportDialog.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Clement Brisset on 8/12/13.
|
||||
// Copyright 2013 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 "InterfaceConfig.h"
|
||||
|
||||
#include <QStandardPaths>
|
||||
#include <QGridLayout>
|
||||
#include <QSplitter>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <PathUtils.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "VoxelImportDialog.h"
|
||||
#include "voxels/VoxelImporter.h"
|
||||
|
||||
const QString SETTINGS_GROUP_NAME = "VoxelImport";
|
||||
const QString IMPORT_DIALOG_SETTINGS_KEY = "VoxelImportDialogSettings";
|
||||
|
||||
const QString WINDOW_NAME = QObject::tr("Import Voxels");
|
||||
const QString IMPORT_BUTTON_NAME = QObject::tr("Import Voxels");
|
||||
const QString LOADING_BUTTON_NAME = QObject::tr("Loading ...");
|
||||
const QString PLACE_BUTTON_NAME = QObject::tr("Place voxels");
|
||||
const QString IMPORT_INFO = QObject::tr("<b>Import</b> %1 as voxels");
|
||||
const QString CANCEL_BUTTON_NAME = QObject::tr("Cancel");
|
||||
|
||||
const QString DOWNLOAD_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||
const int SHORT_FILE_EXTENSION = 4;
|
||||
const int SECOND_INDEX_LETTER = 1;
|
||||
|
||||
QIcon HiFiIconProvider::icon(QFileIconProvider::IconType type) const {
|
||||
|
||||
// types
|
||||
// Computer, Desktop, Trashcan, Network, Drive, Folder, File
|
||||
QString typeString;
|
||||
|
||||
switch (type) {
|
||||
case QFileIconProvider::Computer:
|
||||
typeString = "computer";
|
||||
break;
|
||||
|
||||
case QFileIconProvider::Desktop:
|
||||
typeString = "desktop";
|
||||
break;
|
||||
|
||||
case QFileIconProvider::Trashcan:
|
||||
case QFileIconProvider::Network:
|
||||
case QFileIconProvider::Drive:
|
||||
case QFileIconProvider::Folder:
|
||||
typeString = "folder";
|
||||
break;
|
||||
|
||||
default:
|
||||
typeString = "file";
|
||||
break;
|
||||
}
|
||||
|
||||
return QIcon(PathUtils::resourcesPath() + "icons/" + typeString + ".svg");
|
||||
}
|
||||
|
||||
QIcon HiFiIconProvider::icon(const QFileInfo &info) const {
|
||||
const QString ext = info.suffix().toLower();
|
||||
|
||||
if (info.isDir()) {
|
||||
if (info.absoluteFilePath() == QDir::homePath()) {
|
||||
return QIcon(PathUtils::resourcesPath() + "icons/home.svg");
|
||||
} else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)) {
|
||||
return QIcon(PathUtils::resourcesPath() + "icons/desktop.svg");
|
||||
} else if (info.absoluteFilePath() == QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)) {
|
||||
return QIcon(PathUtils::resourcesPath() + "icons/documents.svg");
|
||||
}
|
||||
return QIcon(PathUtils::resourcesPath() + "icons/folder.svg");
|
||||
}
|
||||
|
||||
QFileInfo iconFile(PathUtils::resourcesPath() + "icons/" + iconsMap[ext]);
|
||||
if (iconFile.exists() && iconFile.isFile()) {
|
||||
return QIcon(iconFile.filePath());
|
||||
}
|
||||
|
||||
return QIcon(PathUtils::resourcesPath() + "icons/file.svg");
|
||||
}
|
||||
|
||||
QString HiFiIconProvider::type(const QFileInfo &info) const {
|
||||
if (info.isFile()) {
|
||||
if (info.suffix().size() > SHORT_FILE_EXTENSION) {
|
||||
// Capitalize extension
|
||||
return info.suffix().left(SECOND_INDEX_LETTER).toUpper() + info.suffix().mid(SECOND_INDEX_LETTER);
|
||||
}
|
||||
return info.suffix().toUpper();
|
||||
}
|
||||
|
||||
return QFileIconProvider::type(info);
|
||||
}
|
||||
|
||||
VoxelImportDialog::VoxelImportDialog(QWidget* parent) :
|
||||
QFileDialog(parent, WINDOW_NAME, DOWNLOAD_LOCATION, NULL),
|
||||
_cancelButton(CANCEL_BUTTON_NAME, this),
|
||||
_importButton(IMPORT_BUTTON_NAME, this),
|
||||
_importer(Application::getInstance()->getVoxelImporter()),
|
||||
_mode(importMode),
|
||||
_progressBar(this),
|
||||
_didImport(false) {
|
||||
|
||||
setOption(QFileDialog::DontUseNativeDialog, true);
|
||||
setFileMode(QFileDialog::ExistingFile);
|
||||
setViewMode(QFileDialog::Detail);
|
||||
|
||||
setImportTypes();
|
||||
setLayout();
|
||||
|
||||
_progressBar.setRange(0, 100);
|
||||
|
||||
connect(&_importButton, SIGNAL(pressed()), this, SLOT(accept()));
|
||||
connect(&_cancelButton, SIGNAL(pressed()), this, SLOT(cancel()));
|
||||
connect(this, SIGNAL(currentChanged(QString)), SLOT(saveCurrentFile(QString)));
|
||||
}
|
||||
|
||||
void VoxelImportDialog::cancel() {
|
||||
switch (getMode()) {
|
||||
case importMode:
|
||||
_importer->cancel();
|
||||
close();
|
||||
break;
|
||||
default:
|
||||
_importer->reset();
|
||||
setMode(importMode);
|
||||
break;
|
||||
}
|
||||
emit canceled();
|
||||
}
|
||||
|
||||
void VoxelImportDialog::saveSettings(QSettings* settings) {
|
||||
settings->beginGroup(SETTINGS_GROUP_NAME);
|
||||
settings->setValue(IMPORT_DIALOG_SETTINGS_KEY, saveState());
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void VoxelImportDialog::loadSettings(QSettings* settings) {
|
||||
settings->beginGroup(SETTINGS_GROUP_NAME);
|
||||
restoreState(settings->value(IMPORT_DIALOG_SETTINGS_KEY).toByteArray());
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
bool VoxelImportDialog::prompt() {
|
||||
reset();
|
||||
exec();
|
||||
return _didImport;
|
||||
}
|
||||
|
||||
void VoxelImportDialog::reset() {
|
||||
setMode(importMode);
|
||||
_didImport = false;
|
||||
}
|
||||
|
||||
void VoxelImportDialog::setMode(dialogMode mode) {
|
||||
dialogMode previousMode = _mode;
|
||||
_mode = mode;
|
||||
|
||||
switch (_mode) {
|
||||
case importMode:
|
||||
_progressBar.setValue(0);
|
||||
_importButton.setEnabled(true);
|
||||
_importButton.setText(IMPORT_BUTTON_NAME);
|
||||
findChild<QWidget*>("sidebar")->setEnabled(true);
|
||||
findChild<QWidget*>("treeView")->setEnabled(true);
|
||||
findChild<QWidget*>("backButton")->setEnabled(true);
|
||||
findChild<QWidget*>("forwardButton")->setEnabled(true);
|
||||
findChild<QWidget*>("toParentButton")->setEnabled(true);
|
||||
break;
|
||||
case loadingMode:
|
||||
// Connect to VoxelImporter signals
|
||||
connect(_importer, SIGNAL(importProgress(int)), this, SLOT(updateProgressBar(int)));
|
||||
connect(_importer, SIGNAL(importDone()), this, SLOT(afterImport()));
|
||||
|
||||
_importButton.setEnabled(false);
|
||||
_importButton.setText(LOADING_BUTTON_NAME);
|
||||
findChild<QWidget*>("sidebar")->setEnabled(false);
|
||||
findChild<QWidget*>("treeView")->setEnabled(false);
|
||||
findChild<QWidget*>("backButton")->setEnabled(false);
|
||||
findChild<QWidget*>("forwardButton")->setEnabled(false);
|
||||
findChild<QWidget*>("toParentButton")->setEnabled(false);
|
||||
break;
|
||||
case finishedMode:
|
||||
if (previousMode == loadingMode) {
|
||||
// Disconnect from VoxelImporter signals
|
||||
disconnect(_importer, SIGNAL(importProgress(int)), this, SLOT(setProgressBarValue(int)));
|
||||
disconnect(_importer, SIGNAL(importDone()), this, SLOT(afterImport()));
|
||||
}
|
||||
setMode(importMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelImportDialog::setProgressBarValue(int value) {
|
||||
_progressBar.setValue(value);
|
||||
}
|
||||
|
||||
void VoxelImportDialog::accept() {
|
||||
if (getMode() == importMode) {
|
||||
QString filename = getCurrentFile();
|
||||
|
||||
// If file is invalid we ignore the call
|
||||
if (!_importer->validImportFile(filename)) {
|
||||
return;
|
||||
}
|
||||
// Let's prepare the dialog window for import
|
||||
setMode(loadingMode);
|
||||
|
||||
_importer->import(filename);
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelImportDialog::afterImport() {
|
||||
setMode(finishedMode);
|
||||
_didImport = true;
|
||||
close();
|
||||
}
|
||||
|
||||
void VoxelImportDialog::saveCurrentFile(QString filename) {
|
||||
_currentFile = QFileInfo(filename).isFile() ? filename : "";
|
||||
}
|
||||
|
||||
void VoxelImportDialog::setLayout() {
|
||||
QGridLayout* gridLayout = (QGridLayout*) layout();
|
||||
gridLayout->addWidget(&_progressBar, 2, 0, 2, 1);
|
||||
gridLayout->addWidget(&_cancelButton, 2, 1, 2, 1);
|
||||
gridLayout->addWidget(&_importButton, 2, 2, 2, 1);
|
||||
|
||||
// set ObjectName used in qss for styling
|
||||
_progressBar.setObjectName("progressBar");
|
||||
_importButton.setObjectName("importButton");
|
||||
_cancelButton.setObjectName("cancelButton");
|
||||
|
||||
// set fixed size
|
||||
_importButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
_cancelButton.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
_cancelButton.setFlat(true);
|
||||
int progressBarHeight = 7;
|
||||
_progressBar.setFixedHeight(progressBarHeight);
|
||||
_progressBar.setTextVisible(false);
|
||||
|
||||
QGridLayout* subLayout = new QGridLayout();
|
||||
subLayout->addWidget(findChild<QWidget*>("lookInLabel"), 0, 0, 1, 5);
|
||||
|
||||
QSize BUTTON_SIZE = QSize(43, 33);
|
||||
QPushButton* button = (QPushButton*) findChild<QWidget*>("backButton");
|
||||
button->setIcon(QIcon());
|
||||
button->setFixedSize(BUTTON_SIZE);
|
||||
subLayout->addWidget(button, 1, 0, 1, 1);
|
||||
|
||||
button = (QPushButton*) findChild<QWidget*>("forwardButton");
|
||||
button->setIcon(QIcon());
|
||||
button->setFixedSize(BUTTON_SIZE);
|
||||
subLayout->addWidget(button, 1, 1, 1, 1);
|
||||
|
||||
button = (QPushButton*) findChild<QWidget*>("toParentButton");
|
||||
button->setIcon(QIcon());
|
||||
button->setFixedSize(BUTTON_SIZE);
|
||||
subLayout->addWidget(button, 1, 2, 1, 1);
|
||||
|
||||
gridLayout->addLayout(subLayout, 0, 0, 1, 1);
|
||||
|
||||
// hide unused embedded widgets in QFileDialog
|
||||
QWidget* widget = findChild<QWidget*>("lookInCombo");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("newFolderButton");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("listModeButton");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("detailModeButton");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("fileNameEdit");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("fileTypeCombo");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("fileTypeLabel");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("fileNameLabel");
|
||||
widget->hide();
|
||||
|
||||
widget = findChild<QWidget*>("buttonBox");
|
||||
widget->hide();
|
||||
|
||||
QSplitter* splitter = findChild<QSplitter*>("splitter");
|
||||
splitter->setHandleWidth(0);
|
||||
|
||||
// remove blue outline on Mac
|
||||
widget = findChild<QWidget*>("sidebar");
|
||||
widget->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
|
||||
widget = findChild<QWidget*>("treeView");
|
||||
widget->setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
|
||||
QFile styleSheet(PathUtils::resourcesPath() + "styles/import_dialog.qss");
|
||||
if (styleSheet.open(QIODevice::ReadOnly)) {
|
||||
QDir::setCurrent(PathUtils::resourcesPath());
|
||||
setStyleSheet(styleSheet.readAll());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VoxelImportDialog::setImportTypes() {
|
||||
QFile config(PathUtils::resourcesPath() + "config/config.json");
|
||||
config.open(QFile::ReadOnly | QFile::Text);
|
||||
QJsonDocument document = QJsonDocument::fromJson(config.readAll());
|
||||
if (!document.isNull() && !document.isEmpty()) {
|
||||
|
||||
QString importFormatsInfo;
|
||||
QString importFormatsFilterList;
|
||||
QHash<QString, QString> iconsMap;
|
||||
|
||||
QJsonObject configObject = document.object();
|
||||
if (!configObject.isEmpty()) {
|
||||
QJsonArray fileFormats = configObject["importFormats"].toArray();
|
||||
int formatsCounter = 0;
|
||||
foreach (const QJsonValue& fileFormat, fileFormats) {
|
||||
QJsonObject fileFormatObject = fileFormat.toObject();
|
||||
|
||||
QString ext(fileFormatObject["extension"].toString());
|
||||
QString icon(fileFormatObject.value("icon").toString());
|
||||
|
||||
if (formatsCounter > 0) {
|
||||
importFormatsInfo.append(",");
|
||||
}
|
||||
|
||||
// set ' or' on last import type text
|
||||
if (formatsCounter == fileFormats.count() - 1) {
|
||||
importFormatsInfo.append(" or");
|
||||
}
|
||||
|
||||
importFormatsFilterList.append(QString("*.%1 ").arg(ext));
|
||||
importFormatsInfo.append(" .").append(ext);
|
||||
iconsMap[ext] = icon;
|
||||
formatsCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
// set custom file icons
|
||||
setIconProvider(new HiFiIconProvider(iconsMap));
|
||||
setNameFilter(importFormatsFilterList);
|
||||
|
||||
setLabelText(QFileDialog::LookIn, QString(IMPORT_INFO).arg(importFormatsInfo));
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
//
|
||||
// VoxelImportDialog.h
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Clement Brisset on 8/12/13.
|
||||
// Copyright 2013 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_VoxelImportDialog_h
|
||||
#define hifi_VoxelImportDialog_h
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QPushButton>
|
||||
#include <QProgressBar>
|
||||
#include <QLabel>
|
||||
#include <QFileIconProvider>
|
||||
#include <QHash>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "voxels/VoxelImporter.h"
|
||||
|
||||
class HiFiIconProvider : public QFileIconProvider {
|
||||
public:
|
||||
HiFiIconProvider(const QHash<QString, QString> map) { iconsMap = map; };
|
||||
virtual QIcon icon(IconType type) const;
|
||||
virtual QIcon icon(const QFileInfo &info) const;
|
||||
virtual QString type(const QFileInfo &info) const;
|
||||
QHash<QString, QString> iconsMap;
|
||||
};
|
||||
|
||||
enum dialogMode {
|
||||
importMode,
|
||||
loadingMode,
|
||||
finishedMode
|
||||
};
|
||||
|
||||
class VoxelImportDialog : public QFileDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VoxelImportDialog(QWidget* parent = NULL);
|
||||
|
||||
QString getCurrentFile() const { return _currentFile; }
|
||||
dialogMode getMode() const { return _mode; }
|
||||
|
||||
void setMode(dialogMode mode);
|
||||
void reset();
|
||||
bool prompt();
|
||||
void loadSettings(QSettings* settings);
|
||||
void saveSettings(QSettings* settings);
|
||||
|
||||
signals:
|
||||
void canceled();
|
||||
|
||||
private slots:
|
||||
void setProgressBarValue(int value);
|
||||
void accept();
|
||||
void cancel();
|
||||
void saveCurrentFile(QString filename);
|
||||
void afterImport();
|
||||
|
||||
private:
|
||||
QPushButton _cancelButton;
|
||||
QString _currentFile;
|
||||
QPushButton _importButton;
|
||||
VoxelImporter* _importer;
|
||||
dialogMode _mode;
|
||||
QProgressBar _progressBar;
|
||||
bool _didImport;
|
||||
|
||||
void setLayout();
|
||||
void setImportTypes();
|
||||
};
|
||||
|
||||
#endif // hifi_VoxelImportDialog_h
|
|
@ -37,6 +37,10 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
if (!_gridProgram.isLinked()) {
|
||||
if (!_gridProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/grid.vert")) {
|
||||
qDebug() << "Failed to compile: " + _gridProgram.log();
|
||||
return;
|
||||
}
|
||||
if (!_gridProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/grid.frag")) {
|
||||
qDebug() << "Failed to compile: " + _gridProgram.log();
|
||||
return;
|
||||
|
@ -70,8 +74,8 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
xColor color = getColor();
|
||||
glm::vec3 position = getPosition();
|
||||
|
||||
const int MINOR_GRID_DIVISIONS = 100;
|
||||
const int MAJOR_GRID_DIVISIONS = 50;
|
||||
const int MINOR_GRID_DIVISIONS = 200;
|
||||
const int MAJOR_GRID_DIVISIONS = 100;
|
||||
const float MAX_COLOR = 255.0f;
|
||||
|
||||
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
//
|
||||
// LocalVoxelsOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Clément Brisset on 2/28/14.
|
||||
// Copyright 2014 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 this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <GlowEffect.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "LocalVoxelsOverlay.h"
|
||||
#include "voxels/VoxelSystem.h"
|
||||
|
||||
QMap<QString, WeakVoxelSystemPointer> LocalVoxelsOverlay::_voxelSystemMap;
|
||||
|
||||
LocalVoxelsOverlay::LocalVoxelsOverlay() :
|
||||
Volume3DOverlay(),
|
||||
_voxelCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
LocalVoxelsOverlay::LocalVoxelsOverlay(const LocalVoxelsOverlay* localVoxelsOverlay) :
|
||||
Volume3DOverlay(localVoxelsOverlay),
|
||||
_voxelCount(localVoxelsOverlay->_voxelCount)
|
||||
{
|
||||
}
|
||||
|
||||
LocalVoxelsOverlay::~LocalVoxelsOverlay() {
|
||||
_voxelSystem->changeTree(new VoxelTree());
|
||||
_voxelSystem.clear();
|
||||
if (_voxelSystemMap.value(_treeName).isNull()) {
|
||||
_voxelSystemMap.remove(_treeName);
|
||||
}
|
||||
_tree.clear();
|
||||
LocalVoxelsList::getInstance()->remove(_treeName);
|
||||
}
|
||||
|
||||
void LocalVoxelsOverlay::update(float deltatime) {
|
||||
if (!_voxelSystem->isInitialized()) {
|
||||
_voxelSystem->init();
|
||||
}
|
||||
|
||||
_tree->lockForRead();
|
||||
if (_visible && _voxelCount != _tree->getOctreeElementsCount()) {
|
||||
_voxelCount = _tree->getOctreeElementsCount();
|
||||
_voxelSystem->forceRedrawEntireTree();
|
||||
}
|
||||
_tree->unlock();
|
||||
}
|
||||
|
||||
void LocalVoxelsOverlay::render(RenderArgs* args) {
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
float size = glm::length(dimensions);
|
||||
if (_visible && size > 0 && _voxelSystem && _voxelSystem->isInitialized()) {
|
||||
|
||||
float glowLevel = getGlowLevel();
|
||||
Glower* glower = NULL;
|
||||
if (glowLevel > 0.0f) {
|
||||
glower = new Glower(glowLevel);
|
||||
}
|
||||
|
||||
glPushMatrix(); {
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glScalef(dimensions.x, dimensions.y, dimensions.z);
|
||||
_voxelSystem->render();
|
||||
} glPopMatrix();
|
||||
|
||||
if (glower) {
|
||||
delete glower;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) {
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
|
||||
if (properties.property("scale").isValid()) {
|
||||
setSize(properties.property("scale").toVariant().toFloat());
|
||||
}
|
||||
|
||||
QScriptValue treeName = properties.property("name");
|
||||
if (treeName.isValid()) {
|
||||
if ((_treeName = treeName.toString()) == DOMAIN_TREE_NAME) {
|
||||
qDebug() << "addOverlay(): Can't create overlay from domain tree";
|
||||
return;
|
||||
}
|
||||
_tree = LocalVoxelsList::getInstance()->getTree(_treeName);
|
||||
if (_tree.isNull()) {
|
||||
qDebug() << "addOverlay(): Invalid tree name";
|
||||
return;
|
||||
}
|
||||
|
||||
_voxelSystem = _voxelSystemMap[_treeName];
|
||||
if (_voxelSystem.isNull()) {
|
||||
_voxelSystem = StrongVoxelSystemPointer(new VoxelSystem(1,
|
||||
DEFAULT_MAX_VOXELS_PER_SYSTEM,
|
||||
_tree.data()));
|
||||
_voxelSystemMap.insert(_treeName, _voxelSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalVoxelsOverlay* LocalVoxelsOverlay::createClone() const {
|
||||
return new LocalVoxelsOverlay(this);
|
||||
}
|
||||
|
||||
QScriptValue LocalVoxelsOverlay::getProperty(const QString& property) {
|
||||
if (property == "scale") {
|
||||
return vec3toScriptValue(_scriptEngine, getDimensions());
|
||||
}
|
||||
if (property == "name") {
|
||||
return _treeName;
|
||||
}
|
||||
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
//
|
||||
// LocalVoxelsOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Clément Brisset on 2/28/14.
|
||||
// Copyright 2014 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_LocalVoxelsOverlay_h
|
||||
#define hifi_LocalVoxelsOverlay_h
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QScriptValue>
|
||||
#include <QMap>
|
||||
#include <QSharedPointer>
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include <LocalVoxelsList.h>
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
typedef QSharedPointer<VoxelSystem> StrongVoxelSystemPointer;
|
||||
typedef QWeakPointer<VoxelSystem> WeakVoxelSystemPointer;
|
||||
|
||||
class LocalVoxelsOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocalVoxelsOverlay();
|
||||
LocalVoxelsOverlay(const LocalVoxelsOverlay* localVoxelsOverlay);
|
||||
~LocalVoxelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
|
||||
virtual LocalVoxelsOverlay* createClone() const;
|
||||
private:
|
||||
static QMap<QString, WeakVoxelSystemPointer> _voxelSystemMap; // treeName/voxelSystem
|
||||
|
||||
QString _treeName;
|
||||
StrongVoxelTreePointer _tree; // so that the tree doesn't get freed
|
||||
unsigned long _voxelCount;
|
||||
StrongVoxelSystemPointer _voxelSystem;
|
||||
};
|
||||
|
||||
#endif // hifi_LocalVoxelsOverlay_h
|
|
@ -21,7 +21,6 @@
|
|||
#include "ImageOverlay.h"
|
||||
#include "Line3DOverlay.h"
|
||||
#include "LocalModelsOverlay.h"
|
||||
#include "LocalVoxelsOverlay.h"
|
||||
#include "ModelOverlay.h"
|
||||
#include "Overlays.h"
|
||||
#include "Rectangle3DOverlay.h"
|
||||
|
@ -86,7 +85,7 @@ void Overlays::renderHUD() {
|
|||
QReadLocker lock(&_lock);
|
||||
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlaysHUD) {
|
||||
|
@ -118,7 +117,7 @@ void Overlays::renderWorld(bool drawFront, RenderArgs::RenderMode renderMode, Re
|
|||
float myAvatarScale = 1.0f;
|
||||
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
|
@ -176,8 +175,6 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
|
|||
thisOverlay = new Line3DOverlay();
|
||||
} else if (type == "grid") {
|
||||
thisOverlay = new Grid3DOverlay();
|
||||
} else if (type == "localvoxels") {
|
||||
thisOverlay = new LocalVoxelsOverlay();
|
||||
} else if (type == "localmodels") {
|
||||
thisOverlay = new LocalModelsOverlay(Application::getInstance()->getEntityClipboardRenderer());
|
||||
} else if (type == "model") {
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
//
|
||||
// VoxelHideShowThread.cpp
|
||||
// interface/src/voxels
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/1/13.
|
||||
// Copyright 2013 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 <QDebug>
|
||||
#include <NodeList.h>
|
||||
#include <PerfStat.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "VoxelHideShowThread.h"
|
||||
|
||||
VoxelHideShowThread::VoxelHideShowThread(VoxelSystem* theSystem) :
|
||||
_theSystem(theSystem) {
|
||||
}
|
||||
|
||||
bool VoxelHideShowThread::process() {
|
||||
const quint64 MSECS_TO_USECS = 1000;
|
||||
const quint64 SECS_TO_USECS = 1000 * MSECS_TO_USECS;
|
||||
const quint64 FRAME_RATE = 60;
|
||||
const quint64 USECS_PER_FRAME = SECS_TO_USECS / FRAME_RATE; // every 60fps
|
||||
|
||||
quint64 start = usecTimestampNow();
|
||||
_theSystem->checkForCulling();
|
||||
quint64 end = usecTimestampNow();
|
||||
quint64 elapsed = end - start;
|
||||
|
||||
bool showExtraDebugging = Application::getInstance()->getLogger()->extraDebugging();
|
||||
if (showExtraDebugging && elapsed > USECS_PER_FRAME) {
|
||||
qDebug() << "VoxelHideShowThread::process()... checkForCulling took" << elapsed;
|
||||
}
|
||||
|
||||
if (isStillRunning()) {
|
||||
if (elapsed < USECS_PER_FRAME) {
|
||||
quint64 sleepFor = USECS_PER_FRAME - elapsed;
|
||||
usleep(sleepFor);
|
||||
}
|
||||
}
|
||||
return isStillRunning(); // keep running till they terminate us
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
//
|
||||
// VoxelHideShowThread.h
|
||||
// interface/src/voxels
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/1/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
//
|
||||
// Threaded or non-threaded voxel persistence
|
||||
//
|
||||
// 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_VoxelHideShowThread_h
|
||||
#define hifi_VoxelHideShowThread_h
|
||||
|
||||
#include <GenericThread.h>
|
||||
#include "VoxelSystem.h"
|
||||
|
||||
/// Generalized threaded processor for handling received inbound packets.
|
||||
class VoxelHideShowThread : public GenericThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
VoxelHideShowThread(VoxelSystem* theSystem);
|
||||
|
||||
protected:
|
||||
/// Implements generic processing behavior for this thread.
|
||||
virtual bool process();
|
||||
|
||||
private:
|
||||
VoxelSystem* _theSystem;
|
||||
};
|
||||
|
||||
#endif // hifi_VoxelHideShowThread_h
|
|
@ -1,119 +0,0 @@
|
|||
//
|
||||
// VoxelImporter.cpp
|
||||
// interface/src/voxels
|
||||
//
|
||||
// Created by Clement Brisset on 8/9/13.
|
||||
// Copyright 2013 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 this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include <Application.h>
|
||||
#include <LocalVoxelsList.h>
|
||||
|
||||
#include "voxels/VoxelImporter.h"
|
||||
|
||||
const QStringList SUPPORTED_EXTENSIONS = QStringList() << "png" << "svo" << "schematic";
|
||||
|
||||
class ImportTask : public QObject, public QRunnable {
|
||||
public:
|
||||
ImportTask(const QString &filename);
|
||||
void run();
|
||||
|
||||
private:
|
||||
QString _filename;
|
||||
};
|
||||
|
||||
VoxelImporter::VoxelImporter() :
|
||||
_voxelTree(true),
|
||||
_task(NULL)
|
||||
{
|
||||
LocalVoxelsList::getInstance()->addPersistantTree(IMPORT_TREE_NAME, &_voxelTree);
|
||||
|
||||
connect(&_voxelTree, SIGNAL(importProgress(int)), this, SIGNAL(importProgress(int)));
|
||||
}
|
||||
|
||||
VoxelImporter::~VoxelImporter() {
|
||||
cleanupTask();
|
||||
}
|
||||
|
||||
void VoxelImporter::cancel() {
|
||||
if (_task) {
|
||||
disconnect(_task, 0, 0, 0);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
void VoxelImporter::reset() {
|
||||
_voxelTree.eraseAllOctreeElements();
|
||||
cleanupTask();
|
||||
}
|
||||
|
||||
void VoxelImporter::import(const QString& filename) {
|
||||
// If present, abort existing import
|
||||
if (_task) {
|
||||
cleanupTask();
|
||||
}
|
||||
|
||||
// If not already done, we switch to the local tree
|
||||
if (Application::getInstance()->getSharedVoxelSystem()->getTree() != &_voxelTree) {
|
||||
Application::getInstance()->getSharedVoxelSystem()->changeTree(&_voxelTree);
|
||||
}
|
||||
|
||||
// Creation and launch of the import task on the thread pool
|
||||
_task = new ImportTask(filename);
|
||||
connect(_task, SIGNAL(destroyed()), SLOT(finishImport()));
|
||||
QThreadPool::globalInstance()->start(_task);
|
||||
}
|
||||
|
||||
void VoxelImporter::cleanupTask() {
|
||||
// If a task is running, we cancel it and put the pointer to null
|
||||
if (_task) {
|
||||
_task = NULL;
|
||||
_voxelTree.cancelImport();
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelImporter::finishImport() {
|
||||
cleanupTask();
|
||||
emit importDone();
|
||||
}
|
||||
|
||||
bool VoxelImporter::validImportFile(const QString& filename) {
|
||||
QFileInfo fileInfo = QFileInfo(filename);
|
||||
return fileInfo.isFile() && SUPPORTED_EXTENSIONS.indexOf(fileInfo.suffix().toLower()) != -1;
|
||||
}
|
||||
|
||||
ImportTask::ImportTask(const QString &filename)
|
||||
: _filename(filename)
|
||||
{
|
||||
setAutoDelete(true);
|
||||
}
|
||||
|
||||
void ImportTask::run() {
|
||||
VoxelSystem* voxelSystem = Application::getInstance()->getSharedVoxelSystem();
|
||||
// We start by cleaning up the shared voxel system just in case
|
||||
voxelSystem->killLocalVoxels();
|
||||
|
||||
// Then we call the right method for the job
|
||||
if (_filename.endsWith(".png", Qt::CaseInsensitive)) {
|
||||
voxelSystem->getTree()->readFromSquareARGB32Pixels(_filename.toLocal8Bit().data());
|
||||
} else if (_filename.endsWith(".svo", Qt::CaseInsensitive)) {
|
||||
voxelSystem->getTree()->readFromSVOFile(_filename.toLocal8Bit().data());
|
||||
} else if (_filename.endsWith(".schematic", Qt::CaseInsensitive)) {
|
||||
voxelSystem->getTree()->readFromSchematicFile(_filename.toLocal8Bit().data());
|
||||
} else {
|
||||
// We should never get here.
|
||||
qDebug() << "[ERROR] Invalid file extension." << endl;
|
||||
}
|
||||
|
||||
// Here we reaverage the tree so that it is ready for preview
|
||||
voxelSystem->getTree()->reaverageOctreeElements();
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
//
|
||||
// VoxelImporter.h
|
||||
// interface/src/voxels
|
||||
//
|
||||
// Created by Clement Brisset on 8/9/13.
|
||||
// Copyright 2013 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_VoxelImporter_h
|
||||
#define hifi_VoxelImporter_h
|
||||
|
||||
#include <QThread>
|
||||
#include <QRunnable>
|
||||
#include <QStringList>
|
||||
|
||||
#include "voxels/VoxelSystem.h"
|
||||
|
||||
class ImportTask;
|
||||
|
||||
class VoxelImporter : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VoxelImporter();
|
||||
~VoxelImporter();
|
||||
|
||||
void reset();
|
||||
void cancel();
|
||||
VoxelTree* getVoxelTree() { return &_voxelTree; }
|
||||
bool validImportFile(const QString& filename);
|
||||
|
||||
public slots:
|
||||
void import(const QString& filename);
|
||||
|
||||
signals:
|
||||
void importDone();
|
||||
void importProgress(int);
|
||||
|
||||
private:
|
||||
VoxelTree _voxelTree;
|
||||
ImportTask* _task;
|
||||
|
||||
void cleanupTask();
|
||||
|
||||
private slots:
|
||||
void finishImport();
|
||||
};
|
||||
|
||||
#endif // hifi_VoxelImporter_h
|
File diff suppressed because it is too large
Load diff
|
@ -1,246 +0,0 @@
|
|||
//
|
||||
// VoxelSystem.h
|
||||
// interface/src/voxels
|
||||
//
|
||||
// Created by Philip on 12/31/12.
|
||||
// Copyright 2012 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_VoxelSystem_h
|
||||
#define hifi_VoxelSystem_h
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include <NodeData.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <VoxelTree.h>
|
||||
#include <OctreePersistThread.h>
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
||||
class ProgramObject;
|
||||
|
||||
const int NUM_CHILDREN = 8;
|
||||
|
||||
|
||||
class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook {
|
||||
Q_OBJECT
|
||||
|
||||
friend class VoxelHideShowThread;
|
||||
|
||||
public:
|
||||
VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = DEFAULT_MAX_VOXELS_PER_SYSTEM, VoxelTree* tree = NULL);
|
||||
~VoxelSystem();
|
||||
|
||||
void setDataSourceUUID(const QUuid& dataSourceUUID) { _dataSourceUUID = dataSourceUUID; }
|
||||
const QUuid& getDataSourceUUID() const { return _dataSourceUUID; }
|
||||
|
||||
int parseData(const QByteArray& packet);
|
||||
|
||||
bool isInitialized() { return _initialized; }
|
||||
virtual void init();
|
||||
void render();
|
||||
|
||||
void changeTree(VoxelTree* newTree);
|
||||
VoxelTree* getTree() const { return _tree; }
|
||||
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
|
||||
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
|
||||
unsigned long getVoxelsUpdated() const { return _voxelsUpdated; }
|
||||
unsigned long getVoxelsRendered() const { return _voxelsInReadArrays; }
|
||||
unsigned long getVoxelsWritten() const { return _voxelsInWriteArrays; }
|
||||
unsigned long getAbandonedVoxels() const { return _freeIndexes.size(); }
|
||||
|
||||
ViewFrustum* getLastCulledViewFrustum() { return &_lastCulledViewFrustum; }
|
||||
|
||||
void setMaxVoxels(unsigned long maxVoxels);
|
||||
long int getMaxVoxels() const { return _maxVoxels; }
|
||||
unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; }
|
||||
unsigned long getVoxelMemoryUsageVBO() const { return _memoryUsageVBO; }
|
||||
bool hasVoxelMemoryUsageGPU() const { return _hasMemoryUsageGPU; }
|
||||
unsigned long getVoxelMemoryUsageGPU();
|
||||
|
||||
void killLocalVoxels();
|
||||
|
||||
virtual void hideOutOfView(bool forceFullFrustum = false);
|
||||
bool hasViewChanged();
|
||||
bool isViewChanging();
|
||||
|
||||
virtual void elementDeleted(OctreeElement* element);
|
||||
virtual void elementUpdated(OctreeElement* element);
|
||||
|
||||
public slots:
|
||||
void nodeAdded(SharedNodePointer node);
|
||||
void nodeKilled(SharedNodePointer node);
|
||||
|
||||
|
||||
// Methods that recurse tree
|
||||
void forceRedrawEntireTree();
|
||||
void clearAllNodesBufferIndex();
|
||||
|
||||
void setDisableFastVoxelPipeline(bool disableFastVoxelPipeline);
|
||||
|
||||
protected:
|
||||
float _treeScale;
|
||||
unsigned long _maxVoxels;
|
||||
VoxelTree* _tree;
|
||||
|
||||
void setupNewVoxelsForDrawing();
|
||||
static const bool DONT_BAIL_EARLY; // by default we will bail early, if you want to force not bailing, then use this
|
||||
void setupNewVoxelsForDrawingSingleNode(bool allowBailEarly = true);
|
||||
|
||||
/// called on the hide/show thread to hide any out of view voxels and show any newly in view voxels.
|
||||
void checkForCulling();
|
||||
|
||||
/// single pass to remove old VBO data and fill it with correct current view, used when switching LOD or needing to force
|
||||
/// a full redraw of everything in view
|
||||
void recreateVoxelGeometryInView();
|
||||
|
||||
glm::vec3 computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const;
|
||||
|
||||
virtual void updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
||||
float voxelScale, const nodeColor& color);
|
||||
virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
|
||||
|
||||
virtual void applyScaleAndBindProgram(bool texture); /// used in render() to apply shadows and textures
|
||||
virtual void removeScaleAndReleaseProgram(bool texture); /// stop the shaders for shadows and textures
|
||||
|
||||
private:
|
||||
// disallow copying of VoxelSystem objects
|
||||
VoxelSystem(const VoxelSystem&);
|
||||
VoxelSystem& operator= (const VoxelSystem&);
|
||||
|
||||
bool _initialized;
|
||||
int _callsToTreesToArrays;
|
||||
|
||||
// Operation functions for tree recursion methods
|
||||
static int _nodeCount;
|
||||
static bool killSourceVoxelsOperation(OctreeElement* element, void* extraData);
|
||||
static bool forceRedrawEntireTreeOperation(OctreeElement* element, void* extraData);
|
||||
static bool clearAllNodesBufferIndexOperation(OctreeElement* element, void* extraData);
|
||||
static bool hideOutOfViewOperation(OctreeElement* element, void* extraData);
|
||||
static bool hideAllSubTreeOperation(OctreeElement* element, void* extraData);
|
||||
static bool showAllSubTreeOperation(OctreeElement* element, void* extraData);
|
||||
static bool getVoxelEnclosingOperation(OctreeElement* element, void* extraData);
|
||||
static bool recreateVoxelGeometryInViewOperation(OctreeElement* element, void* extraData);
|
||||
|
||||
int updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, bool forceDraw);
|
||||
int forceRemoveNodeFromArrays(VoxelTreeElement* node);
|
||||
|
||||
void copyWrittenDataToReadArraysFullVBOs();
|
||||
void copyWrittenDataToReadArraysPartialVBOs();
|
||||
|
||||
void updateVBOs();
|
||||
|
||||
unsigned long getFreeMemoryGPU();
|
||||
|
||||
// these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here
|
||||
static float _maxDistance;
|
||||
static float _minDistance;
|
||||
|
||||
GLfloat* _readVerticesArray;
|
||||
GLubyte* _readColorsArray;
|
||||
|
||||
QReadWriteLock _writeArraysLock;
|
||||
QReadWriteLock _readArraysLock;
|
||||
|
||||
|
||||
GLfloat* _writeVerticesArray;
|
||||
GLubyte* _writeColorsArray;
|
||||
bool* _writeVoxelDirtyArray;
|
||||
bool* _readVoxelDirtyArray;
|
||||
unsigned long _voxelsUpdated;
|
||||
unsigned long _voxelsInReadArrays;
|
||||
unsigned long _voxelsInWriteArrays;
|
||||
|
||||
bool _writeRenderFullVBO;
|
||||
bool _readRenderFullVBO;
|
||||
|
||||
int _setupNewVoxelsForDrawingLastElapsed;
|
||||
quint64 _setupNewVoxelsForDrawingLastFinished;
|
||||
quint64 _lastViewCulling;
|
||||
quint64 _lastViewIsChanging;
|
||||
quint64 _lastAudit;
|
||||
int _lastViewCullingElapsed;
|
||||
bool _hasRecentlyChanged;
|
||||
|
||||
void initVoxelMemory();
|
||||
void cleanupVoxelMemory();
|
||||
|
||||
GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO
|
||||
GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes
|
||||
|
||||
GLuint _vboVerticesID;
|
||||
GLuint _vboColorsID;
|
||||
|
||||
GLuint _vboIndicesTop;
|
||||
GLuint _vboIndicesBottom;
|
||||
GLuint _vboIndicesLeft;
|
||||
GLuint _vboIndicesRight;
|
||||
GLuint _vboIndicesFront;
|
||||
GLuint _vboIndicesBack;
|
||||
|
||||
ViewFrustum _lastKnownViewFrustum;
|
||||
ViewFrustum _lastStableViewFrustum;
|
||||
ViewFrustum* _viewFrustum;
|
||||
|
||||
ViewFrustum _lastCulledViewFrustum; // used for hide/show visible passes
|
||||
bool _culledOnce;
|
||||
|
||||
void setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]);
|
||||
|
||||
int newTreeToArrays(VoxelTreeElement* currentNode);
|
||||
|
||||
void copyWrittenDataToReadArrays(bool fullVBOs);
|
||||
|
||||
void updateFullVBOs(); // all voxels in the VBO
|
||||
void updatePartialVBOs(); // multiple segments, only dirty voxels
|
||||
|
||||
bool _voxelsDirty;
|
||||
|
||||
static ProgramObject _program;
|
||||
static ProgramObject _perlinModulateProgram;
|
||||
|
||||
static void bindPerlinModulateProgram();
|
||||
|
||||
int _hookID;
|
||||
std::vector<glBufferIndex> _freeIndexes;
|
||||
QMutex _freeIndexLock;
|
||||
|
||||
void freeBufferIndex(glBufferIndex index);
|
||||
void clearFreeBufferIndexes();
|
||||
glBufferIndex getNextBufferIndex();
|
||||
|
||||
bool _falseColorizeBySource;
|
||||
QUuid _dataSourceUUID;
|
||||
|
||||
int _voxelServerCount;
|
||||
unsigned long _memoryUsageRAM;
|
||||
unsigned long _memoryUsageVBO;
|
||||
unsigned long _initialMemoryUsageGPU;
|
||||
bool _hasMemoryUsageGPU;
|
||||
|
||||
bool _inSetupNewVoxelsForDrawing;
|
||||
bool _useFastVoxelPipeline;
|
||||
|
||||
bool _inhideOutOfView;
|
||||
|
||||
float _lastKnownVoxelSizeScale;
|
||||
int _lastKnownBoundaryLevelAdjust;
|
||||
|
||||
// haze
|
||||
bool _drawHaze;
|
||||
float _farHazeDistance;
|
||||
glm::vec3 _hazeColor;
|
||||
};
|
||||
|
||||
#endif // hifi_VoxelSystem_h
|
|
@ -5,7 +5,7 @@ setup_hifi_library(Network Script)
|
|||
|
||||
include_glm()
|
||||
|
||||
link_hifi_libraries(audio shared octree voxels networking gpu model fbx)
|
||||
link_hifi_libraries(audio shared octree networking gpu model fbx)
|
||||
|
||||
# call macro to include our dependency includes and bubble them up via a property on our target
|
||||
include_dependency_includes()
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <GLMHelpers.h>
|
||||
#include <StreamUtils.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
#include "AvatarData.h"
|
||||
|
||||
|
|
|
@ -895,17 +895,6 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel,
|
||||
const Collision& collision) {
|
||||
QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID);
|
||||
if (entityScript.property("collisionWithVoxel").isValid()) {
|
||||
QScriptValueList args;
|
||||
args << entityID.toScriptValue(_entitiesScriptEngine);
|
||||
args << collisionToScriptValue(_entitiesScriptEngine, collision);
|
||||
entityScript.property("collisionWithVoxel").call(entityScript, args);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB,
|
||||
const Collision& collision) {
|
||||
QScriptValue entityScriptA = loadEntityScript(idA);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue