first cut at light entity

This commit is contained in:
ZappoMan 2014-10-22 08:41:31 -07:00
parent 0d77063e1e
commit 2f9766e051
11 changed files with 366 additions and 6 deletions

View file

@ -133,7 +133,7 @@ EntityPropertyDialogBox = (function () {
array.push({ label: "Visible:", value: properties.visible });
index++;
if (properties.type == "Box" || properties.type == "Sphere") {
if (properties.type == "Box" || properties.type == "Sphere" || properties.type == "Light") {
array.push({ label: "Color:", type: "header" });
index++;
array.push({ label: "Red:", value: properties.color.red });
@ -143,6 +143,11 @@ EntityPropertyDialogBox = (function () {
array.push({ label: "Blue:", value: properties.color.blue });
index++;
}
if (properties.type == "Light") {
array.push({ label: "Spot Light:", value: properties.isSpotlight });
index++;
}
array.push({ button: "Cancel" });
index++;
@ -237,12 +242,16 @@ EntityPropertyDialogBox = (function () {
properties.lifetime = array[index++].value;
properties.visible = array[index++].value;
if (properties.type == "Box" || properties.type == "Sphere") {
if (properties.type == "Box" || properties.type == "Sphere" || properties.type == "Light") {
index++; // skip header
properties.color.red = array[index++].value;
properties.color.green = array[index++].value;
properties.color.blue = array[index++].value;
}
if (properties.type == "Light") {
properties.isSpotlight = array[index++].value;
}
Entities.editEntity(editModelID, properties);
selectionDisplay.select(editModelID, false);
}

View file

@ -73,6 +73,7 @@ var toolBar = (function () {
newModelButton,
newCubeButton,
newSphereButton,
newLightButton,
browseModelsButton,
loadURLMenuItem,
loadFileMenuItem,
@ -157,6 +158,15 @@ var toolBar = (function () {
visible: true
});
newLightButton = toolBar.addTool({
imageURL: toolIconUrl + "add-sphere.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
width: toolWidth,
height: toolHeight,
alpha: 0.9,
visible: true
});
}
function toggleNewModelButton(active) {
@ -319,7 +329,23 @@ var toolBar = (function () {
color: { red: 255, green: 0, blue: 0 }
});
} else {
print("Can't create box: Box would be out of bounds.");
print("Can't create sphere: Sphere would be out of bounds.");
}
return true;
}
if (newLightButton === toolBar.clicked(clickedOverlay)) {
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
if (position.x > 0 && position.y > 0 && position.z > 0) {
Entities.addEntity({
type: "Light",
position: position,
dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION },
color: { red: 255, green: 0, blue: 0 }
});
} else {
print("Can't create Light: Light would be out of bounds.");
}
return true;
}

View file

@ -24,6 +24,7 @@
#include "EntityTreeRenderer.h"
#include "RenderableBoxEntityItem.h"
#include "RenderableLightEntityItem.h"
#include "RenderableModelEntityItem.h"
#include "RenderableSphereEntityItem.h"
@ -39,6 +40,7 @@ EntityTreeRenderer::EntityTreeRenderer() :
REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory)
REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory)
REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory)
REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory)
}
EntityTreeRenderer::~EntityTreeRenderer() {

View file

@ -0,0 +1,98 @@
//
// RenderableLightEntityItem.cpp
// interface/src
//
// Created by Brad Hefta-Gaub on 8/6/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 <glm/gtx/quaternion.hpp>
#include <FBXReader.h>
#include "InterfaceConfig.h"
#include <PerfStat.h>
#include <LightEntityItem.h>
#include "Application.h"
#include "Menu.h"
#include "EntityTreeRenderer.h"
#include "RenderableLightEntityItem.h"
EntityItem* RenderableLightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableLightEntityItem(entityID, properties);
}
void RenderableLightEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RenderableLightEntityItem::render");
assert(getType() == EntityTypes::Light);
glm::vec3 position = getPositionInMeters();
glm::vec3 center = getCenterInMeters();
glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE;
glm::quat rotation = getRotation();
float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z);
const float MAX_COLOR = 255.0f;
float red = getColor()[RED_INDEX] / MAX_COLOR;
float green = getColor()[GREEN_INDEX] / MAX_COLOR;
float blue = getColor()[BLUE_INDEX] / MAX_COLOR;
float alpha = getLocalRenderAlpha();
/*
/// Adds a point light to render for the current frame.
void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f),
float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f);
/// Adds a spot light to render for the current frame.
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f),
float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f,
const glm::vec3& direction = glm::vec3(0.0f, 0.0f, -1.0f), float exponent = 0.0f, float cutoff = PI);
*/
glm::vec3 ambient = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 diffuse = glm::vec3(red, green, blue);
glm::vec3 specular = glm::vec3(red, green, blue);
glm::vec3 direction = IDENTITY_FRONT * rotation;
float constantAttenuation = 1.0f;
float linearAttenuation = 0.0f;
float quadraticAttenuation = 0.0f;
if (_isSpotlight) {
Application::getInstance()->getDeferredLightingEffect()->addSpotLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation,
direction);
} else {
Application::getInstance()->getDeferredLightingEffect()->addPointLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
}
bool wantDebug = false;
if (wantDebug) {
glColor4f(red, green, blue, alpha);
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
glPushMatrix();
glm::vec3 positionToCenter = center - position;
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
glScalef(dimensions.x, dimensions.y, dimensions.z);
Application::getInstance()->getDeferredLightingEffect()->renderWireSphere(0.5f, 15, 15);
glPopMatrix();
glPopMatrix();
}
};

View file

@ -0,0 +1,40 @@
//
// RenderableLightEntityItem.h
// interface/src/entities
//
// Created by Brad Hefta-Gaub on 8/6/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_RenderableLightEntityItem_h
#define hifi_RenderableLightEntityItem_h
#include <glm/glm.hpp>
#include <stdint.h>
#include <EntityTree.h>
#include <Octree.h>
#include <OctreePacketData.h>
#include <OctreeRenderer.h>
#include <PacketHeaders.h>
#include <SharedUtil.h>
#include <ViewFrustum.h>
#include <LightEntityItem.h>
class RenderableLightEntityItem : public LightEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableLightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
LightEntityItem(entityItemID, properties)
{ }
virtual void render(RenderArgs* args);
};
#endif // hifi_RenderableLightEntityItem_h

View file

@ -68,6 +68,7 @@ EntityItemProperties::EntityItemProperties() :
_animationFPS(ModelEntityItem::DEFAULT_ANIMATION_FPS),
_glowLevel(0.0f),
_localRenderAlpha(1.0f),
_isSpotlight(false),
_naturalDimensions(1.0f, 1.0f, 1.0f),
_colorChanged(false),
@ -78,7 +79,6 @@ EntityItemProperties::EntityItemProperties() :
_animationFPSChanged(false),
_glowLevelChanged(false),
_localRenderAlphaChanged(false),
_defaultSettings(true)
{
}
@ -120,6 +120,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_ANGULAR_DAMPING, angularDamping);
CHECK_PROPERTY_CHANGE(PROP_IGNORE_FOR_COLLISIONS, ignoreForCollisions);
CHECK_PROPERTY_CHANGE(PROP_COLLISIONS_WILL_MOVE, collisionsWillMove);
CHECK_PROPERTY_CHANGE(PROP_IS_SPOTLIGHT, isSpotlight);
return changedProperties;
}
@ -161,6 +162,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
COPY_PROPERTY_TO_QSCRIPTVALUE(ignoreForCollisions);
COPY_PROPERTY_TO_QSCRIPTVALUE(collisionsWillMove);
COPY_PROPERTY_TO_QSCRIPTVALUE(isSpotlight);
// Sitting properties support
QScriptValue sittingPoints = engine->newObject();
@ -220,6 +222,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localRenderAlpha, setLocalRenderAlpha);
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(ignoreForCollisions, setIgnoreForCollisions);
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(collisionsWillMove, setCollisionsWillMove);
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(isSpotlight, setIsSpotlight);
_lastEdited = usecTimestampNow();
}
@ -370,6 +373,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, appendValue, properties.getVisible());
APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, properties.getIgnoreForCollisions());
APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, properties.getCollisionsWillMove());
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, properties.getIsSpotlight());
}
if (propertyCount > 0) {
int endOfEntityItemData = packetData->getUncompressedByteOffset();
@ -568,6 +572,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_FOR_COLLISIONS, bool, setIgnoreForCollisions);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONS_WILL_MOVE, bool, setCollisionsWillMove);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
return valid;
}
@ -622,6 +627,7 @@ void EntityItemProperties::markAllChanged() {
_animationFPSChanged = true;
_glowLevelChanged = true;
_localRenderAlphaChanged = true;
_isSpotlightChanged = true;
}
AACube EntityItemProperties::getMaximumAACubeInTreeUnits() const {

View file

@ -65,7 +65,10 @@ enum EntityPropertyList {
PROP_IGNORE_FOR_COLLISIONS,
PROP_COLLISIONS_WILL_MOVE,
PROP_LAST_ITEM = PROP_COLLISIONS_WILL_MOVE
// property used by Light entity
PROP_IS_SPOTLIGHT,
PROP_LAST_ITEM = PROP_IS_SPOTLIGHT
};
typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
@ -83,6 +86,7 @@ class EntityItemProperties {
friend class ModelEntityItem; // TODO: consider removing this friend relationship and use public methods
friend class BoxEntityItem; // TODO: consider removing this friend relationship and use public methods
friend class SphereEntityItem; // TODO: consider removing this friend relationship and use public methods
friend class LightEntityItem; // TODO: consider removing this friend relationship and use public methods
public:
EntityItemProperties();
virtual ~EntityItemProperties() { };
@ -233,6 +237,9 @@ public:
bool getCollisionsWillMove() const { return _collisionsWillMove; }
void setCollisionsWillMove(bool value) { _collisionsWillMove = value; _collisionsWillMoveChanged = true; }
bool getIsSpotlight() const { return _isSpotlight; }
void setIsSpotlight(bool value) { _isSpotlight = value; _isSpotlightChanged = true; }
void setLastEdited(quint64 usecTime) { _lastEdited = usecTime; }
private:
@ -288,8 +295,10 @@ private:
float _animationFPS;
float _glowLevel;
float _localRenderAlpha;
bool _isSpotlight;
QVector<SittingPoint> _sittingPoints;
glm::vec3 _naturalDimensions;
bool _colorChanged;
bool _modelURLChanged;
@ -299,6 +308,7 @@ private:
bool _animationFPSChanged;
bool _glowLevelChanged;
bool _localRenderAlphaChanged;
bool _isSpotlightChanged;
bool _defaultSettings;
};

View file

@ -19,6 +19,7 @@
#include "EntityTypes.h"
#include "BoxEntityItem.h"
#include "LightEntityItem.h"
#include "ModelEntityItem.h"
#include "SphereEntityItem.h"
@ -33,6 +34,7 @@ const QString ENTITY_TYPE_NAME_UNKNOWN = "Unknown";
REGISTER_ENTITY_TYPE(Model)
REGISTER_ENTITY_TYPE(Box)
REGISTER_ENTITY_TYPE(Sphere)
REGISTER_ENTITY_TYPE(Light)
const QString& EntityTypes::getEntityTypeName(EntityType entityType) {

View file

@ -33,7 +33,8 @@ public:
Model,
Box,
Sphere,
LAST = Sphere
Light,
LAST = Light
} EntityType;
static const QString& getEntityTypeName(EntityType entityType);

View file

@ -0,0 +1,99 @@
//
// LightEntityItem.cpp
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 12/4/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 <ByteCountCoding.h>
#include "EntityTree.h"
#include "EntityTreeElement.h"
#include "LightEntityItem.h"
EntityItem* LightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new LightEntityItem(entityID, properties);
}
// our non-pure virtual subclass for now...
LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
EntityItem(entityItemID, properties)
{
_type = EntityTypes::Light;
setProperties(properties, true);
// a light is not collide-able so we make it's shape be a tiny sphere at origin
_emptyShape.setTranslation(glm::vec3(0.0f,0.0f,0.0f));
_emptyShape.setRadius(0.0f);
}
EntityItemProperties LightEntityItem::getProperties() const {
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
properties.setColor(getXColor());
properties.setGlowLevel(getGlowLevel());
properties.setIsSpotlight(getIsSpotlight());
return properties;
}
bool LightEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) {
bool somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight);
if (somethingChanged) {
bool wantDebug = false;
if (wantDebug) {
uint64_t now = usecTimestampNow();
int elapsed = now - getLastEdited();
qDebug() << "LightEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
"now=" << now << " getLastEdited()=" << getLastEdited();
}
setLastEdited(properties.getLastEdited());
}
return somethingChanged;
}
int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
int bytesRead = 0;
const unsigned char* dataAt = data;
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight);
return bytesRead;
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
EntityPropertyFlags LightEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;
return requestedProperties;
}
void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, getIsSpotlight());
}

View file

@ -0,0 +1,67 @@
//
// LightEntityItem.h
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 12/4/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_LightEntityItem_h
#define hifi_LightEntityItem_h
#include <SphereShape.h>
#include "EntityItem.h"
class LightEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
ALLOW_INSTANTIATION // This class can be instantiated
// methods for getting/setting all properties of an entity
virtual EntityItemProperties getProperties() const;
virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false);
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const;
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
void setColor(const xColor& value) {
_color[RED_INDEX] = value.red;
_color[GREEN_INDEX] = value.green;
_color[BLUE_INDEX] = value.blue;
}
bool getIsSpotlight() const { return _isSpotlight; }
void setIsSpotlight(bool value) { _isSpotlight = value; }
virtual const Shape& getCollisionShapeInMeters() const { return _emptyShape; }
protected:
virtual void recalculateCollisionShape() { /* nothing to do */ }
rgbColor _color;
bool _isSpotlight;
SphereShape _emptyShape;
};
#endif // hifi_LightEntityItem_h