mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-07 22:31:06 +02:00
first pass at adding actual particles to the ParticleTree
This commit is contained in:
parent
50833cf04c
commit
86ffbc3d33
10 changed files with 434 additions and 30 deletions
|
@ -178,8 +178,11 @@ public:
|
|||
Octree(bool shouldReaverage = false);
|
||||
~Octree();
|
||||
|
||||
/// Your tree class must implement this to create the correct element type
|
||||
virtual OctreeElement* createNewElement(unsigned char * octalCode = NULL) const = 0;
|
||||
|
||||
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
|
||||
// own definition. Implement these to allow your octree based server to support editing
|
||||
virtual bool handlesEditPacketType(PACKET_TYPE packetType) const { return false; }
|
||||
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||
unsigned char* editData, int maxLength) { return 0; }
|
||||
|
|
|
@ -52,16 +52,52 @@ protected:
|
|||
public:
|
||||
virtual void init(unsigned char * octalCode); /// Your subclass must call init on construction.
|
||||
virtual ~OctreeElement();
|
||||
|
||||
// methods you can and should override to implement your tree functionality
|
||||
|
||||
/// Adds a child to the current element. Override this if there is additional child initialization your class needs.
|
||||
virtual OctreeElement* addChildAtIndex(int childIndex);
|
||||
|
||||
/// Override this to implement LOD averaging on changes to the tree.
|
||||
virtual void calculateAverageFromChildren() { }
|
||||
|
||||
/// Override this to implement LOD collapsing and identical child pruning on changes to the tree.
|
||||
virtual bool collapseChildren() { return false; }
|
||||
|
||||
/// Should this element be considered to have content in it. This will be used in collision and ray casting methods.
|
||||
/// By default we assume that only leaves are actual content, but some octrees may have different semantics.
|
||||
virtual bool hasContent() const { return isLeaf(); }
|
||||
|
||||
/// Override this to break up large octree elements when an edit operation is performed on a smaller octree element.
|
||||
/// For example, if the octrees represent solid cubes and a delete of a smaller octree element is done then the
|
||||
/// meaningful split would be to break the larger cube into smaller cubes of the same color/texture.
|
||||
virtual void splitChildren() { }
|
||||
|
||||
/// Override to indicate that this element requires a split before editing lower elements in the octree
|
||||
virtual bool requiresSplit() const { return false; }
|
||||
|
||||
/// Override to serialize the state of this element. This is used for persistance and for transmission across the network.
|
||||
virtual bool appendElementData(OctreePacketData* packetData) const { return true; }
|
||||
|
||||
/// Override to deserialize the state of this element. This is used for loading from a persisted file or from reading
|
||||
/// from the network.
|
||||
virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args)
|
||||
{ return 0; }
|
||||
|
||||
/// Override to indicate that the item is currently rendered in the rendering engine. By default we assume that if
|
||||
/// the element should be rendered, then your rendering engine is rendering. But some rendering engines my have cases
|
||||
/// where an element is not actually rendering all should render elements. If the isRendered() state doesn't match the
|
||||
/// shouldRender() state, the tree will remark elements as changed even in cases there the elements have not changed.
|
||||
virtual bool isRendered() const { return getShouldRender(); }
|
||||
|
||||
|
||||
// Base class methods you don't need to implement
|
||||
const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode.pointer : &_octalCode.buffer[0]; }
|
||||
OctreeElement* getChildAtIndex(int childIndex) const;
|
||||
void deleteChildAtIndex(int childIndex);
|
||||
OctreeElement* removeChildAtIndex(int childIndex);
|
||||
virtual OctreeElement* addChildAtIndex(int childIndex);
|
||||
void safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0); // handles deletion of all descendents
|
||||
|
||||
virtual void calculateAverageFromChildren() { };
|
||||
virtual bool collapseChildren() { return false; };
|
||||
|
||||
const AABox& getAABox() const { return _box; }
|
||||
const glm::vec3& getCorner() const { return _box.getCorner(); }
|
||||
|
@ -70,12 +106,6 @@ public:
|
|||
|
||||
float getEnclosingRadius() const;
|
||||
|
||||
virtual bool hasContent() const { return isLeaf(); }
|
||||
virtual void splitChildren() { }
|
||||
virtual bool requiresSplit() const { return false; }
|
||||
virtual bool appendElementData(OctreePacketData* packetData) const { return true; }
|
||||
virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args)
|
||||
{ return 0; }
|
||||
|
||||
bool isInView(const ViewFrustum& viewFrustum) const;
|
||||
ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const;
|
||||
|
@ -104,9 +134,6 @@ public:
|
|||
void setShouldRender(bool shouldRender);
|
||||
bool getShouldRender() const { return _shouldRender; }
|
||||
|
||||
/// we assume that if you should be rendered, then your subclass is rendering, but this allows subclasses to
|
||||
/// implement alternate rendering strategies
|
||||
virtual bool isRendered() const { return getShouldRender(); }
|
||||
|
||||
void setSourceUUID(const QUuid& sourceID);
|
||||
QUuid getSourceUUID() const;
|
||||
|
|
|
@ -13,6 +13,9 @@ bool OctreePacketData::_debug = false;
|
|||
uint64_t OctreePacketData::_totalBytesOfOctalCodes = 0;
|
||||
uint64_t OctreePacketData::_totalBytesOfBitMasks = 0;
|
||||
uint64_t OctreePacketData::_totalBytesOfColor = 0;
|
||||
uint64_t OctreePacketData::_totalBytesOfValues = 0;
|
||||
uint64_t OctreePacketData::_totalBytesOfPositions = 0;
|
||||
uint64_t OctreePacketData::_totalBytesOfRawData = 0;
|
||||
|
||||
|
||||
|
||||
|
@ -210,14 +213,22 @@ bool OctreePacketData::appendBitMask(unsigned char bitmask) {
|
|||
}
|
||||
|
||||
bool OctreePacketData::appendColor(const nodeColor& color) {
|
||||
return appendColor(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]);
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendColor(const rgbColor& color) {
|
||||
return appendColor(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]);
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendColor(colorPart red, colorPart green, colorPart blue) {
|
||||
// eventually we can make this use a dictionary...
|
||||
bool success = false;
|
||||
const int BYTES_PER_COLOR = 3;
|
||||
if (_bytesAvailable > BYTES_PER_COLOR) {
|
||||
// handles checking compression...
|
||||
if (append(color[RED_INDEX])) {
|
||||
if (append(color[GREEN_INDEX])) {
|
||||
if (append(color[BLUE_INDEX])) {
|
||||
if (append(red)) {
|
||||
if (append(green)) {
|
||||
if (append(blue)) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
@ -230,6 +241,90 @@ bool OctreePacketData::appendColor(const nodeColor& color) {
|
|||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(uint8_t value) {
|
||||
bool success = append(value); // used unsigned char version
|
||||
if (success) {
|
||||
_bytesOfValues++;
|
||||
_totalBytesOfValues++;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(uint16_t value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfValues += length;
|
||||
_totalBytesOfValues += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(uint32_t value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfValues += length;
|
||||
_totalBytesOfValues += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(uint64_t value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfValues += length;
|
||||
_totalBytesOfValues += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(float value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfValues += length;
|
||||
_totalBytesOfValues += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendValue(const glm::vec3& value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfValues += length;
|
||||
_totalBytesOfValues += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendPosition(const glm::vec3& value) {
|
||||
const unsigned char* data = (const unsigned char*)&value;
|
||||
int length = sizeof(value);
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfPositions += length;
|
||||
_totalBytesOfPositions += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool OctreePacketData::appendRawData(const unsigned char* data, int length) {
|
||||
bool success = append(data, length);
|
||||
if (success) {
|
||||
_bytesOfRawData += length;
|
||||
_totalBytesOfRawData += length;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
uint64_t OctreePacketData::_compressContentTime = 0;
|
||||
uint64_t OctreePacketData::_compressContentCalls = 0;
|
||||
|
||||
|
|
|
@ -106,6 +106,36 @@ public:
|
|||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendColor(const nodeColor& color);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendColor(const rgbColor& color);
|
||||
|
||||
/// appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendColor(colorPart red, colorPart green, colorPart blue);
|
||||
|
||||
/// appends a unsigned 8 bit int to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(uint8_t value);
|
||||
|
||||
/// appends a unsigned 16 bit int to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(uint16_t value);
|
||||
|
||||
/// appends a unsigned 32 bit int to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(uint32_t value);
|
||||
|
||||
/// appends a unsigned 64 bit int to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(uint64_t value);
|
||||
|
||||
/// appends a float value to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(float value);
|
||||
|
||||
/// appends a non-position vector to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendValue(const glm::vec3& value);
|
||||
|
||||
/// appends a position to the end of the stream, may fail if new data stream is too long to fit in packet
|
||||
bool appendPosition(const glm::vec3& value);
|
||||
|
||||
/// appends raw bytes, might fail if byte would cause packet to be too large
|
||||
bool appendRawData(const unsigned char* data, int length);
|
||||
|
||||
/// returns a byte offset from beginning of the uncompressed stream based on offset from end.
|
||||
/// Positive offsetFromEnd returns that many bytes before the end of uncompressed stream
|
||||
int getUncompressedByteOffset(int offsetFromEnd = 0) const { return _bytesInUse - offsetFromEnd; }
|
||||
|
@ -167,6 +197,10 @@ private:
|
|||
int _bytesOfOctalCodes;
|
||||
int _bytesOfBitMasks;
|
||||
int _bytesOfColor;
|
||||
int _bytesOfValues;
|
||||
int _bytesOfPositions;
|
||||
int _bytesOfRawData;
|
||||
|
||||
int _bytesOfOctalCodesCurrentSubTree;
|
||||
|
||||
static bool _debug;
|
||||
|
@ -177,6 +211,9 @@ private:
|
|||
static uint64_t _totalBytesOfOctalCodes;
|
||||
static uint64_t _totalBytesOfBitMasks;
|
||||
static uint64_t _totalBytesOfColor;
|
||||
static uint64_t _totalBytesOfValues;
|
||||
static uint64_t _totalBytesOfPositions;
|
||||
static uint64_t _totalBytesOfRawData;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__OctreePacketData__) */
|
101
libraries/particles/src/Particle.cpp
Normal file
101
libraries/particles/src/Particle.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
//
|
||||
// Particle.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#include <SharedUtil.h> // usecTimestampNow()
|
||||
|
||||
#include "Particle.h"
|
||||
|
||||
uint32_t Particle::_nextID = 0;
|
||||
|
||||
|
||||
Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity) {
|
||||
init(position, radius, color, velocity);
|
||||
}
|
||||
|
||||
Particle::Particle() {
|
||||
rgbColor noColor = { 0, 0, 0 };
|
||||
init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0));
|
||||
}
|
||||
|
||||
Particle::~Particle() {
|
||||
}
|
||||
|
||||
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity) {
|
||||
_id = _nextID;
|
||||
_nextID++;
|
||||
_lastUpdated = usecTimestampNow();
|
||||
|
||||
_position = position;
|
||||
_radius = radius;
|
||||
memcpy(_color, color, sizeof(_color));
|
||||
_velocity = velocity;
|
||||
}
|
||||
|
||||
|
||||
bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
||||
|
||||
bool success = packetData->appendValue(getID());
|
||||
|
||||
if (success) {
|
||||
success = packetData->appendValue(getLastUpdated());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendValue(getRadius());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendPosition(getPosition());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendColor(getColor());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendValue(getVelocity());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int Particle::expectedBytes() {
|
||||
int expectedBytes = sizeof(uint32_t) + sizeof(uint64_t) + sizeof(float) +
|
||||
sizeof(glm::vec3) + sizeof(rgbColor) + sizeof(glm::vec3);
|
||||
return expectedBytes;
|
||||
}
|
||||
|
||||
int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) {
|
||||
int bytesRead = 0;
|
||||
if (bytesLeftToRead >= expectedBytes()) {
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
// id
|
||||
memcpy(&_id, dataAt, sizeof(_id));
|
||||
dataAt += sizeof(_id);
|
||||
|
||||
// lastupdated
|
||||
memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated));
|
||||
dataAt += sizeof(_lastUpdated);
|
||||
|
||||
// radius
|
||||
memcpy(&_radius, dataAt, sizeof(_radius));
|
||||
dataAt += sizeof(_radius);
|
||||
|
||||
// position
|
||||
memcpy(&_position, dataAt, sizeof(_position));
|
||||
dataAt += sizeof(_position);
|
||||
|
||||
// color
|
||||
memcpy(_color, dataAt, sizeof(_color));
|
||||
dataAt += sizeof(_color);
|
||||
|
||||
// velocity
|
||||
memcpy(&_velocity, dataAt, sizeof(_velocity));
|
||||
dataAt += sizeof(_velocity);
|
||||
|
||||
bytesRead = expectedBytes();
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
46
libraries/particles/src/Particle.h
Normal file
46
libraries/particles/src/Particle.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// Particle.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__Particle__
|
||||
#define __hifi__Particle__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <OctreePacketData.h>
|
||||
|
||||
class Particle {
|
||||
public:
|
||||
Particle();
|
||||
Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity);
|
||||
virtual ~Particle();
|
||||
virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity);
|
||||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
float getRadius() const { return _radius; }
|
||||
const glm::vec3& getVelocity() const { return _velocity; }
|
||||
uint64_t getLastUpdated() const { return _lastUpdated; }
|
||||
uint32_t getID() const { return _id; }
|
||||
|
||||
bool appendParticleData(OctreePacketData* packetData) const;
|
||||
int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
|
||||
static int expectedBytes();
|
||||
protected:
|
||||
glm::vec3 _position;
|
||||
rgbColor _color;
|
||||
float _radius;
|
||||
glm::vec3 _velocity;
|
||||
uint64_t _lastUpdated;
|
||||
uint32_t _id;
|
||||
static uint32_t _nextID;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Particle__) */
|
|
@ -17,3 +17,12 @@ ParticleTreeElement* ParticleTree::createNewElement(unsigned char * octalCode) c
|
|||
return newElement;
|
||||
}
|
||||
|
||||
bool ParticleTree::handlesEditPacketType(PACKET_TYPE packetType) const {
|
||||
return false; // not yet.
|
||||
}
|
||||
|
||||
int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||
unsigned char* editData, int maxLength) {
|
||||
|
||||
return 0; // not yet... soon...
|
||||
}
|
||||
|
|
|
@ -16,8 +16,20 @@ class ParticleTree : public Octree {
|
|||
Q_OBJECT
|
||||
public:
|
||||
ParticleTree(bool shouldReaverage = false);
|
||||
|
||||
/// Implements our type specific root element factory
|
||||
virtual ParticleTreeElement* createNewElement(unsigned char * octalCode = NULL) const;
|
||||
|
||||
/// Type safe version of getRoot()
|
||||
ParticleTreeElement* getRoot() { return (ParticleTreeElement*)_rootNode; }
|
||||
|
||||
|
||||
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
|
||||
// own definition. Implement these to allow your octree based server to support editing
|
||||
virtual bool handlesEditPacketType(PACKET_TYPE packetType) const;
|
||||
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||
unsigned char* editData, int maxLength);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
@ -33,17 +33,60 @@ void ParticleTreeElement::init(unsigned char* octalCode) {
|
|||
_voxelMemoryUsage += sizeof(ParticleTreeElement);
|
||||
}
|
||||
|
||||
ParticleTreeElement* ParticleTreeElement::addChildAtIndex(int index) {
|
||||
return (ParticleTreeElement*)OctreeElement::addChildAtIndex(index);
|
||||
}
|
||||
|
||||
|
||||
bool ParticleTreeElement::appendElementData(OctreePacketData* packetData) const {
|
||||
// will write to the encoded stream all of the contents of this element
|
||||
return true;
|
||||
bool success = true; // assume the best...
|
||||
|
||||
// write our particles out...
|
||||
uint16_t numberOfParticles = _particles.size();
|
||||
success = packetData->appendValue(numberOfParticles);
|
||||
|
||||
if (success) {
|
||||
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||
const Particle& particle = _particles[i];
|
||||
success = particle.appendParticleData(packetData);
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
int ParticleTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args) {
|
||||
|
||||
// will read from the encoded stream all of the contents of this element
|
||||
return 0;
|
||||
|
||||
|
||||
const unsigned char* dataAt = data;
|
||||
int bytesRead = 0;
|
||||
uint16_t numberOfParticles = 0;
|
||||
int expectedBytesPerParticle = Particle::expectedBytes();
|
||||
|
||||
_particles.clear();
|
||||
|
||||
if (bytesLeftToRead >= sizeof(numberOfParticles)) {
|
||||
|
||||
// read our particles in....
|
||||
numberOfParticles = *(uint16_t*)dataAt;
|
||||
dataAt += sizeof(numberOfParticles);
|
||||
bytesLeftToRead -= sizeof(numberOfParticles);
|
||||
bytesRead += sizeof(numberOfParticles);
|
||||
|
||||
if (bytesLeftToRead >= (numberOfParticles * expectedBytesPerParticle)) {
|
||||
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||
int bytesForThisParticle = _particles[i].readParticleDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||
dataAt += bytesForThisParticle;
|
||||
bytesLeftToRead -= bytesForThisParticle;
|
||||
bytesRead += bytesForThisParticle;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
// will average a "common reduced LOD view" from the the child elements...
|
||||
|
|
|
@ -10,8 +10,12 @@
|
|||
#ifndef __hifi__ParticleTreeElement__
|
||||
#define __hifi__ParticleTreeElement__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <OctreeElement.h>
|
||||
|
||||
#include "Particle.h"
|
||||
|
||||
class ParticleTree;
|
||||
class ParticleTreeElement;
|
||||
|
||||
|
@ -26,20 +30,47 @@ public:
|
|||
virtual ~ParticleTreeElement();
|
||||
virtual void init(unsigned char * octalCode);
|
||||
|
||||
virtual bool hasContent() const { return isLeaf(); }
|
||||
virtual void splitChildren() {}
|
||||
virtual bool requiresSplit() const { return false; }
|
||||
virtual bool appendElementData(OctreePacketData* packetData) const;
|
||||
virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
|
||||
virtual void calculateAverageFromChildren();
|
||||
virtual bool collapseChildren();
|
||||
virtual bool isRendered() const { return getShouldRender(); }
|
||||
|
||||
// type safe versions of OctreeElement methods
|
||||
ParticleTreeElement* getChildAtIndex(int index) { return (ParticleTreeElement*)OctreeElement::getChildAtIndex(index); }
|
||||
ParticleTreeElement* addChildAtIndex(int index) { return (ParticleTreeElement*)OctreeElement::addChildAtIndex(index); }
|
||||
|
||||
// methods you can and should override to implement your tree functionality
|
||||
|
||||
/// Adds a child to the current element. Override this if there is additional child initialization your class needs.
|
||||
virtual ParticleTreeElement* addChildAtIndex(int index);
|
||||
|
||||
/// Override this to implement LOD averaging on changes to the tree.
|
||||
virtual void calculateAverageFromChildren();
|
||||
|
||||
/// Override this to implement LOD collapsing and identical child pruning on changes to the tree.
|
||||
virtual bool collapseChildren();
|
||||
|
||||
/// Should this element be considered to have content in it. This will be used in collision and ray casting methods.
|
||||
/// By default we assume that only leaves are actual content, but some octrees may have different semantics.
|
||||
virtual bool hasContent() const { return isLeaf(); }
|
||||
|
||||
/// Override this to break up large octree elements when an edit operation is performed on a smaller octree element.
|
||||
/// For example, if the octrees represent solid cubes and a delete of a smaller octree element is done then the
|
||||
/// meaningful split would be to break the larger cube into smaller cubes of the same color/texture.
|
||||
virtual void splitChildren() { }
|
||||
|
||||
/// Override to indicate that this element requires a split before editing lower elements in the octree
|
||||
virtual bool requiresSplit() const { return false; }
|
||||
|
||||
/// Override to serialize the state of this element. This is used for persistance and for transmission across the network.
|
||||
virtual bool appendElementData(OctreePacketData* packetData) const;
|
||||
|
||||
/// Override to deserialize the state of this element. This is used for loading from a persisted file or from reading
|
||||
/// from the network.
|
||||
virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
|
||||
|
||||
/// Override to indicate that the item is currently rendered in the rendering engine. By default we assume that if
|
||||
/// the element should be rendered, then your rendering engine is rendering. But some rendering engines my have cases
|
||||
/// where an element is not actually rendering all should render elements. If the isRendered() state doesn't match the
|
||||
/// shouldRender() state, the tree will remark elements as changed even in cases there the elements have not changed.
|
||||
virtual bool isRendered() const { return getShouldRender(); }
|
||||
|
||||
protected:
|
||||
std::vector<Particle> _particles;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__ParticleTreeElement__) */
|
Loading…
Reference in a new issue