354 lines · 11.5 KB · Text
RawDownload
////  PolyVoxEntityItem.cpp//  libraries/entities/src////  Created by Seth Alves on 5/11/15.//  Copyright 2015 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 "PolyVoxEntityItem.h" #include <glm/gtx/transform.hpp> #include <QByteArray>#include <QDebug>#include <QWriteLocker> #include <ByteCountCoding.h>  #include "EntitiesLogging.h"#include "EntityItemProperties.h"#include "EntityTree.h"#include "EntityTreeElement.h" bool PolyVoxEntityItem::isEdged(PolyVoxSurfaceStyle surfaceStyle) {    switch (surfaceStyle) {        case PolyVoxEntityItem::SURFACE_CUBIC:        case PolyVoxEntityItem::SURFACE_MARCHING_CUBES:            return false;        case PolyVoxEntityItem::SURFACE_EDGED_CUBIC:        case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES:            return true;    }    return false;} const glm::vec3 PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE = glm::vec3(32, 32, 32);const float PolyVoxEntityItem::MAX_VOXEL_DIMENSION = 128.0f;const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(PolyVoxEntityItem::makeEmptyVoxelData());const PolyVoxEntityItem::PolyVoxSurfaceStyle PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE =    PolyVoxEntityItem::SURFACE_EDGED_CUBIC;const QString PolyVoxEntityItem::DEFAULT_X_TEXTURE_URL = QString("");const QString PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL = QString("");const QString PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL = QString(""); EntityItemPointer PolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {    std::shared_ptr<PolyVoxEntityItem> entity(new PolyVoxEntityItem(entityID), [](PolyVoxEntityItem* ptr) { ptr->deleteLater(); });    entity->setProperties(properties);    return entity;} QByteArray PolyVoxEntityItem::makeEmptyVoxelData(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize) {    int rawSize = voxelXSize * voxelYSize * voxelZSize;     QByteArray uncompressedData = QByteArray(rawSize, '\0');    QByteArray newVoxelData;    QDataStream writer(&newVoxelData, QIODevice::WriteOnly | QIODevice::Truncate);    writer << voxelXSize << voxelYSize << voxelZSize;     QByteArray compressedData = qCompress(uncompressedData, 9);    writer << compressedData;     return newVoxelData;} PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {    _type = EntityTypes::PolyVox;} void PolyVoxEntityItem::setVoxelVolumeSize(const glm::vec3& voxelVolumeSize_) {    auto voxelVolumeSize = glm::clamp(glm::round(voxelVolumeSize_), glm::vec3(1.0f), glm::vec3(MAX_VOXEL_DIMENSION));     withWriteLock([&] {        _needsRenderUpdate |= _voxelVolumeSize != voxelVolumeSize;        _voxelVolumeSize = voxelVolumeSize;    });} glm::vec3 PolyVoxEntityItem::getVoxelVolumeSize() const {    return resultWithReadLock<glm::vec3>([&] {        return _voxelVolumeSize;    });}  EntityItemProperties PolyVoxEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {    EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class @PolyVox_ENTITY_COPY_TO@     return properties;} bool PolyVoxEntityItem::setSubClassProperties(const EntityItemProperties& properties) {    bool somethingChanged = false; @PolyVox_ENTITY_SET_FROM@     return somethingChanged;} EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {    EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); @PolyVox_REQUESTED_PROPS@     return requestedProperties;} void PolyVoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,                                           EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,                                           EntityPropertyFlags& requestedProperties,                                           EntityPropertyFlags& propertyFlags,                                           EntityPropertyFlags& propertiesDidntFit,                                           int& propertyCount,                                           OctreeElement::AppendState& appendState) const {     bool successPropertyFits = true; @PolyVox_ENTITY_APPEND@ } int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,                                                        ReadBitstreamToTreeParams& args,                                                        EntityPropertyFlags& propertyFlags, bool overwriteLocalData,                                                        bool& somethingChanged) {     int bytesRead = 0;    const unsigned char* dataAt = data; @PolyVox_ENTITY_READ@     return bytesRead;} void PolyVoxEntityItem::debugDump() const {    qCDebug(entities) << "PolyVoxEntityItem id:" << getEntityItemID() << "---------------------------------------------";    qCDebug(entities) << "    name:" << _name;    qCDebug(entities) << "    position:" << debugTreeVector(getWorldPosition());    qCDebug(entities) << "    dimensions:" << debugTreeVector(getScaledDimensions());    qCDebug(entities) << "    editedAgo:" << debugTime(getLastEdited(), usecTimestampNow());    qCDebug(entities) << "    pointer:" << this; @PolyVox_ENTITY_DEBUG@ } void PolyVoxEntityItem::setVoxelData(const QByteArray& voxelData) {    withWriteLock([&] {        _voxelData = voxelData;        _voxelDataDirty = true;    });} QByteArray PolyVoxEntityItem::getVoxelData() const {    return resultWithReadLock<QByteArray>([&] {        return _voxelData;    });} void PolyVoxEntityItem::setVoxelSurfaceStyle(uint16_t voxelSurfaceStyle) {    withWriteLock([&] {        _voxelSurfaceStyle = voxelSurfaceStyle;    });} uint16_t PolyVoxEntityItem::getVoxelSurfaceStyle() const {    return resultWithReadLock<uint16_t>([&] {        return _voxelSurfaceStyle;    });} void PolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighborID) {    withWriteLock([&] {        _xNNeighborID = xNNeighborID;    });} EntityItemID PolyVoxEntityItem::getXNNeighborID() const {    return resultWithReadLock<EntityItemID>([&] {        return _xNNeighborID;    });} void PolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighborID) {    withWriteLock([&] {        _yNNeighborID = yNNeighborID;    });} EntityItemID PolyVoxEntityItem::getYNNeighborID() const {    return resultWithReadLock<EntityItemID>([&] {        return _yNNeighborID;    });} void PolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighborID) {    withWriteLock([&] {        _zNNeighborID = zNNeighborID;    });} EntityItemID PolyVoxEntityItem::getZNNeighborID() const {    return resultWithReadLock<EntityItemID>([&] {        return _zNNeighborID;    });} void PolyVoxEntityItem::setXPNeighborID(const EntityItemID& xPNeighborID) {    withWriteLock([&] {        _xPNeighborID = xPNeighborID;    });} EntityItemID PolyVoxEntityItem::getXPNeighborID() const {    return resultWithReadLock<EntityItemID>([&] {        return _xPNeighborID;    });} void PolyVoxEntityItem::setYPNeighborID(const EntityItemID& yPNeighborID) {    withWriteLock([&] {        _yPNeighborID = yPNeighborID;    });} EntityItemID PolyVoxEntityItem::getYPNeighborID() const {    return resultWithReadLock<EntityItemID>([&] {        return _yPNeighborID;    });} void PolyVoxEntityItem::setZPNeighborID(const EntityItemID& zPNeighborID) {    withWriteLock([&] {        _zPNeighborID = zPNeighborID;    });} EntityItemID PolyVoxEntityItem::getZPNeighborID() const {    return resultWithReadLock<EntityItemID>([&] {        return _zPNeighborID;    });} glm::vec3 PolyVoxEntityItem::getSurfacePositionAdjustment() const {    glm::vec3 result;    withReadLock([&] {        glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units        if (isEdged()) {            result = scale / -2.0f;        }        return scale / 2.0f;    });    return result;} glm::mat4 PolyVoxEntityItem::voxelToLocalMatrix() const {    glm::vec3 voxelVolumeSize;    withReadLock([&] {        voxelVolumeSize = _voxelVolumeSize;    });     glm::vec3 dimensions = getScaledDimensions();    glm::vec3 scale = dimensions / voxelVolumeSize; // meters / voxel-units    bool success; // TODO -- Does this actually have to happen in world space?    glm::vec3 center = getCenterPosition(success); // this handles registrationPoint changes    glm::vec3 position = getWorldPosition(success);    glm::vec3 positionToCenter = center - position;     positionToCenter -= dimensions * Vectors::HALF - getSurfacePositionAdjustment();    glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter);    glm::mat4 scaled = glm::scale(centerToCorner, scale);    return scaled;} glm::mat4 PolyVoxEntityItem::localToVoxelMatrix() const {    glm::mat4 localToModelMatrix = glm::inverse(voxelToLocalMatrix());    return localToModelMatrix;} glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix(bool includeBillboard) const {    glm::vec3 position = getWorldPosition();    glm::mat4 translation = glm::translate(position);    glm::mat4 rotation;    if (includeBillboard) {        BillboardMode billboardMode = getBillboardMode();        glm::quat orientation = billboardMode == BillboardMode::NONE ? getWorldOrientation() : getLocalOrientation();        rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, billboardMode, BillboardModeHelpers::getPrimaryViewFrustumPosition()));    } else {        rotation = glm::mat4_cast(getWorldOrientation());    }    return translation * rotation * voxelToLocalMatrix();} glm::mat4 PolyVoxEntityItem::worldToVoxelMatrix(bool includeBillboard) const {    return glm::inverse(voxelToWorldMatrix(includeBillboard));} glm::vec3 PolyVoxEntityItem::voxelCoordsToWorldCoords(const glm::vec3& voxelCoords) const {    glm::vec3 adjustedCoords;    if (isEdged()) {        adjustedCoords = voxelCoords + Vectors::HALF;    } else {        adjustedCoords = voxelCoords - Vectors::HALF;    }    return glm::vec3(voxelToWorldMatrix() * glm::vec4(adjustedCoords, 1.0f));} glm::vec3 PolyVoxEntityItem::worldCoordsToVoxelCoords(const glm::vec3& worldCoords) const {    glm::vec3 result = glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f));    if (isEdged()) {        return result - Vectors::HALF;    }    return result + Vectors::HALF;} glm::vec3 PolyVoxEntityItem::voxelCoordsToLocalCoords(const glm::vec3& voxelCoords) const {    return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 0.0f));} glm::vec3 PolyVoxEntityItem::localCoordsToVoxelCoords(const glm::vec3& localCoords) const {    return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 0.0f));} ShapeType PolyVoxEntityItem::getShapeType() const {    if (_collisionless) {        return SHAPE_TYPE_NONE;    }    return SHAPE_TYPE_COMPOUND;} bool PolyVoxEntityItem::isEdged() const {    return isEdged((PolyVoxSurfaceStyle)_voxelSurfaceStyle);} std::array<EntityItemID, 3> PolyVoxEntityItem::getNNeigborIDs() const {    std::array<EntityItemID, 3> result;    withReadLock([&] {        result = { { _xNNeighborID, _yNNeighborID, _zNNeighborID } };    });    return result;} std::array<EntityItemID, 3> PolyVoxEntityItem::getPNeigborIDs() const {    std::array<EntityItemID, 3> result;    withReadLock([&] {        result = { { _xPNeighborID, _yPNeighborID, _zPNeighborID } };    });    return result;}