Merge branch 'master' of git://github.com/highfidelity/hifi into audio-buffer-size

Conflicts:
	interface/src/Audio.cpp
This commit is contained in:
Ryan Huffman 2015-01-05 14:07:06 -08:00
commit defb2cbffd
158 changed files with 501 additions and 11918 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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
}
]
}
}
]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -11,7 +11,6 @@
#include <glm/gtx/quaternion.hpp>
#include <SharedUtil.h>
#include <VoxelConstants.h>
#include <EventTypes.h>
#include "Application.h"

View file

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

View file

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

View file

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

View file

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

View file

@ -25,7 +25,6 @@
#include <TextRenderer.h>
#include "InterfaceConfig.h"
#include "VoxelConstants.h"
#include "world.h"
#include "Application.h"

View file

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

View file

@ -18,7 +18,7 @@
#include <HeadData.h>
#include <VoxelConstants.h>
#include <OctreeConstants.h> // for IDENTITY_*
#include "FaceModel.h"
#include "InterfaceConfig.h"

View file

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

View file

@ -21,6 +21,7 @@
#include "Menu.h"
#include "SkeletonModel.h"
#include "SkeletonRagdoll.h"
#include "Util.h"
enum StandingFootState {
LEFT_FOOT,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,6 +20,7 @@
#include "ApplicationOverlay.h"
#include "devices/OculusManager.h"
#include "Util.h"
#include "ui/Stats.h"
// Used to fade the UI

View file

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

View file

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

View file

@ -19,8 +19,6 @@
#include <QScreen>
#include <QWindow>
#include <VoxelConstants.h>
#include "MainWindow.h"
#include "Menu.h"
#include "devices/OculusManager.h"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -13,6 +13,7 @@
#include "ScriptEditorWidget.h"
#include <QGridLayout>
#include <QFileDialog>
#include <QFrame>
#include <QLayoutItem>
#include <QMainWindow>

View file

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

View file

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

View file

@ -46,7 +46,7 @@ private:
int _generalStatsWidth;
int _pingStatsWidth;
int _geoStatsWidth;
int _voxelStatsWidth;
int _octreeStatsWidth;
int _lastHorizontalOffset;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,7 +25,6 @@
#include <GLMHelpers.h>
#include <StreamUtils.h>
#include <UUID.h>
#include <VoxelConstants.h>
#include "AvatarData.h"

View file

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