Merge remote-tracking branch 'upstream/master' into plugins

This commit is contained in:
Brad Davis 2015-08-10 21:25:35 -07:00
commit 19d31938d3
45 changed files with 1342 additions and 52 deletions

View file

@ -0,0 +1,225 @@
//
// hydraPaint.js
// examples
//
// Created by Eric Levin on 5/14/15.
// Copyright 2014 High Fidelity, Inc.
//
// This script allows you to paint with the hydra!
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var LEFT = 0;
var RIGHT = 1;
var LASER_WIDTH = 3;
var LASER_COLOR = {
red: 50,
green: 150,
blue: 200
};
var TRIGGER_THRESHOLD = .1;
var MAX_POINTS_PER_LINE = 40;
var LIFETIME = 6000;
var DRAWING_DEPTH = 1;
var LINE_DIMENSIONS = 20;
var MIN_POINT_DISTANCE = 0.01;
var MIN_BRUSH_RADIUS = 0.08;
var MAX_BRUSH_RADIUS = 0.1;
var RIGHT_BUTTON_1 = 7
var RIGHT_BUTTON_2 = 8
var RIGHT_BUTTON_3 = 9;
var RIGHT_BUTTON_4 = 10
var LEFT_BUTTON_1 = 1;
var LEFT_BUTTON_2 = 2;
var LEFT_BUTTON_3 = 3;
var LEFT_BUTTON_4 = 4;
var colorPalette = [{
red: 250,
green: 0,
blue: 0
}, {
red: 214,
green: 91,
blue: 67
}, {
red: 192,
green: 41,
blue: 66
}, {
red: 84,
green: 36,
blue: 55
}, {
red: 83,
green: 119,
blue: 122
}];
var MIN_STROKE_WIDTH = 0.002;
var MAX_STROKE_WIDTH = 0.05;
function controller(side, cycleColorButton) {
this.triggerHeld = false;
this.triggerThreshold = 0.9;
this.side = side;
this.palm = 2 * side;
this.tip = 2 * side + 1;
this.trigger = side;
this.cycleColorButton = cycleColorButton;
this.points = [];
this.normals = [];
this.strokeWidths = [];
this.currentColorIndex = 0;
this.currentColor = colorPalette[this.currentColorIndex];
var self = this;
this.brush = Entities.addEntity({
type: 'Sphere',
position: {
x: 0,
y: 0,
z: 0
},
color: this.currentColor,
dimensions: {
x: MIN_BRUSH_RADIUS,
y: MIN_BRUSH_RADIUS,
z: MIN_BRUSH_RADIUS
}
});
this.cycleColor = function() {
this.currentColor = colorPalette[++this.currentColorIndex];
if (this.currentColorIndex === colorPalette.length - 1) {
this.currentColorIndex = -1;
}
}
this.newLine = function(position) {
this.linePosition = position;
this.line = Entities.addEntity({
position: position,
type: "PolyLine",
color: this.currentColor,
dimensions: {
x: LINE_DIMENSIONS,
y: LINE_DIMENSIONS,
z: LINE_DIMENSIONS
},
lifetime: LIFETIME
});
this.points = [];
this.normals = []
this.strokeWidths = [];
}
this.update = function(deltaTime) {
this.updateControllerState();
var newBrushPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH);
var newBrushPos = Vec3.sum(this.palmPosition, newBrushPosOffset);
var brushRadius = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_BRUSH_RADIUS, MAX_BRUSH_RADIUS)
Entities.editEntity(this.brush, {
position: newBrushPos,
color: this.currentColor,
dimensions: {
x: brushRadius,
y: brushRadius,
z: brushRadius
}
});
if (this.triggerValue > TRIGGER_THRESHOLD && !this.drawing) {
this.newLine(newBrushPos);
this.drawing = true;
} else if (this.drawing && this.triggerValue < TRIGGER_THRESHOLD) {
this.drawing = false;
}
if (this.drawing && this.points.length < MAX_POINTS_PER_LINE) {
var localPoint = Vec3.subtract(newBrushPos, this.linePosition);
if (Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) {
//Need a minimum distance to avoid binormal NANs
return;
}
this.points.push(localPoint);
var normal = computeNormal(newBrushPos, Camera.getPosition());
this.normals.push(normal);
var strokeWidth = map(this.triggerValue, TRIGGER_THRESHOLD, 1, MIN_STROKE_WIDTH, MAX_STROKE_WIDTH);
this.strokeWidths.push(strokeWidth);
Entities.editEntity(this.line, {
linePoints: this.points,
normals: this.normals,
strokeWidths: this.strokeWidths,
color: this.currentColor
});
}
}
this.updateControllerState = function() {
this.cycleColorButtonPressed = Controller.isButtonPressed(this.cycleColorButton);
this.palmPosition = Controller.getSpatialControlPosition(this.palm);
this.tipPosition = Controller.getSpatialControlPosition(this.tip);
this.palmNormal = Controller.getSpatialControlNormal(this.palm);
this.triggerValue = Controller.getTriggerValue(this.trigger);
if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) {
this.cycleColor();
Entities.editEntity(this.brush, {
// color: this.currentColor
});
}
this.prevCycleColorButtonPressed = this.cycleColorButtonPressed;
}
this.cleanup = function() {
Entities.deleteEntity(self.brush);
}
}
function computeNormal(p1, p2) {
return Vec3.normalize(Vec3.subtract(p2, p1));
}
function update(deltaTime) {
leftController.update(deltaTime);
rightController.update(deltaTime);
}
function scriptEnding() {
leftController.cleanup();
rightController.cleanup();
}
function vectorIsZero(v) {
return v.x === 0 && v.y === 0 && v.z === 0;
}
var rightController = new controller(RIGHT, RIGHT_BUTTON_4);
var leftController = new controller(LEFT, LEFT_BUTTON_4);
Script.update.connect(update);
Script.scriptEnding.connect(scriptEnding);
function map(value, min1, max1, min2, max2) {
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
}

View file

@ -0,0 +1,194 @@
//
// mousePaint.js
// examples
//
// Created by Eric Levin on 6/4/15.
// Copyright 2014 High Fidelity, Inc.
//
// This script allows you to paint with the hydra or mouse!
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
var LINE_DIMENSIONS = 10;
var LIFETIME = 6000;
var EVENT_CHANGE_THRESHOLD = 200;
var LINE_WIDTH = .07;
var MAX_POINTS_PER_LINE = 40;
var points = [];
var normals = [];
var deletedLines = [];
var strokeWidths = [];
var count = 0;
var prevEvent = {x: 0, y: 0};
var eventChange;
var MIN_POINT_DISTANCE = .01;
var colorPalette = [{
red: 250,
green: 0,
blue: 0
}, {
red: 214,
green: 91,
blue: 67
}, {
red: 192,
green: 41,
blue: 66
}, {
red: 84,
green: 36,
blue: 55
}, {
red: 83,
green: 119,
blue: 122
}];
var currentColorIndex = 0;
var currentColor = colorPalette[currentColorIndex];
function cycleColor() {
currentColor = colorPalette[++currentColorIndex];
if (currentColorIndex === colorPalette.length - 1) {
currentColorIndex = -1;
}
}
MousePaint();
function MousePaint() {
var DRAWING_DISTANCE = 5;
var lines = [];
var isDrawing = false;
var line, linePosition;
var BRUSH_SIZE = .05;
var brush = Entities.addEntity({
type: 'Sphere',
position: {
x: 0,
y: 0,
z: 0
},
color: currentColor,
dimensions: {
x: BRUSH_SIZE,
y: BRUSH_SIZE,
z: BRUSH_SIZE
}
});
function newLine(position) {
linePosition = position;
line = Entities.addEntity({
position: position,
type: "PolyLine",
color: currentColor,
dimensions: {
x: LINE_DIMENSIONS,
y: LINE_DIMENSIONS,
z: LINE_DIMENSIONS
},
linePoints: [],
lifetime: LIFETIME
});
points = [];
normals = []
strokeWidths = [];
lines.push(line);
}
function mouseMoveEvent(event) {
var pickRay = Camera.computePickRay(event.x, event.y);
count++;
var worldPoint = computeWorldPoint(pickRay);
Entities.editEntity(brush, {
position: worldPoint
});
eventChange = Math.sqrt(Math.pow(event.x - prevEvent.x, 2) + Math.pow(event.y - prevEvent.y, 2));
localPoint = computeLocalPoint(worldPoint);
if (!isDrawing || points.length > MAX_POINTS_PER_LINE || eventChange > EVENT_CHANGE_THRESHOLD ||
Vec3.distance(points[points.length - 1], localPoint) < MIN_POINT_DISTANCE) {
return;
}
points.push(localPoint)
normals.push(computeNormal(worldPoint, pickRay.origin));
strokeWidths.push(LINE_WIDTH);
Entities.editEntity(line, {
strokeWidths: strokeWidths,
linePoints: points,
normals: normals,
});
prevEvent = event;
}
function computeNormal(p1, p2) {
return Vec3.normalize(Vec3.subtract(p2, p1));
}
function computeWorldPoint(pickRay) {
var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE);
return Vec3.sum(pickRay.origin, addVector);
}
function computeLocalPoint(worldPoint) {
var localPoint = Vec3.subtract(worldPoint, linePosition);
return localPoint;
}
function mousePressEvent(event) {
if (!event.isLeftButton) {
isDrawing = false;
return;
}
var pickRay = Camera.computePickRay(event.x, event.y);
prevEvent = {x: event.x, y:event.y};
var worldPoint = computeWorldPoint(pickRay);
newLine(worldPoint);
var localPoint = computeLocalPoint(worldPoint);
points.push(localPoint);
normals.push(computeNormal(worldPoint, pickRay.origin));
strokeWidths.push(0.07);
isDrawing = true;
}
function mouseReleaseEvent() {
isDrawing = false;
}
function keyPressEvent(event) {
if (event.text === "SPACE") {
cycleColor();
Entities.editEntity(brush, {
color: currentColor
});
}
}
function cleanup() {
lines.forEach(function(line) {
// Entities.deleteEntity(line);
});
Entities.deleteEntity(brush);
}
Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Script.scriptEnding.connect(cleanup);
Controller.keyPressEvent.connect(keyPressEvent);
}

View file

@ -595,7 +595,7 @@ function menuItemEvent(menuItem) {
LODManager.LODDecreased.connect(function() {
var warningText = "\n"
+ "Due to the complexity of the content, the \n"
+ "level of detail has been decreased."
+ "level of detail has been decreased. "
+ "You can now see: \n"
+ LODManager.getLODFeedbackText();

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -815,7 +815,7 @@ void Application::initializeGL() {
init();
qCDebug(interfaceapp, "init() complete.");
// create thread for parsing of octee data independent of the main network and rendering threads
// create thread for parsing of octree data independent of the main network and rendering threads
_octreeProcessor.initialize(_enableProcessOctreeThread);
connect(&_octreeProcessor, &OctreePacketProcessor::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch);
_entityEditSender.initialize(_enableProcessOctreeThread);

View file

@ -107,12 +107,14 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
Rig::HeadParameters params;
params.modelRotation = getRotation();
params.modelTranslation = getTranslation();
params.leanSideways = _owningAvatar->getHead()->getFinalLeanSideways();
params.leanForward = _owningAvatar->getHead()->getFinalLeanSideways();
params.torsoTwist = _owningAvatar->getHead()->getTorsoTwist();
params.localHeadOrientation = _owningAvatar->getHead()->getFinalOrientationInLocalFrame();
params.worldHeadOrientation = _owningAvatar->getHead()->getFinalOrientationInWorldFrame();
params.eyeLookAt = _owningAvatar->getHead()->getCorrectedLookAtPosition();
params.eyeLookAt = _owningAvatar->getHead()->getLookAtPosition();
params.eyeSaccade = _owningAvatar->getHead()->getSaccade();
params.leanJointIndex = geometry.leanJointIndex;
params.neckJointIndex = geometry.neckJointIndex;

View file

@ -230,11 +230,13 @@ void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float p
}
void JointState::setRotationInConstrainedFrameInternal(const glm::quat& targetRotation) {
glm::quat parentRotation = computeParentRotation();
_rotationInConstrainedFrame = targetRotation;
_transformChanged = true;
// R' = Rp * Rpre * r' * Rpost
_rotation = parentRotation * _preRotation * _rotationInConstrainedFrame * _postRotation;
if (_rotationInConstrainedFrame != targetRotation) {
glm::quat parentRotation = computeParentRotation();
_rotationInConstrainedFrame = targetRotation;
_transformChanged = true;
// R' = Rp * Rpre * r' * Rpost
_rotation = parentRotation * _preRotation * _rotationInConstrainedFrame * _postRotation;
}
}
void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation) {

View file

@ -27,6 +27,10 @@ void Rig::HeadParameters::dump() const {
axis = glm::axis(worldHeadOrientation);
theta = glm::angle(worldHeadOrientation);
qCDebug(animation, " worldHeadOrientation axis = (%.5f, %.5f, %.5f), theta = %0.5f", axis.x, axis.y, axis.z, theta);
axis = glm::axis(modelRotation);
theta = glm::angle(modelRotation);
qCDebug(animation, " modelRotation axis = (%.5f, %.5f, %.5f), theta = %0.5f", axis.x, axis.y, axis.z, theta);
qCDebug(animation, " modelTranslation = (%.5f, %.5f, %.5f)", modelTranslation.x, modelTranslation.y, modelTranslation.z);
qCDebug(animation, " eyeLookAt = (%.5f, %.5f, %.5f)", eyeLookAt.x, eyeLookAt.y, eyeLookAt.z);
qCDebug(animation, " eyeSaccade = (%.5f, %.5f, %.5f)", eyeSaccade.x, eyeSaccade.y, eyeSaccade.z);
qCDebug(animation, " leanJointIndex = %.d", leanJointIndex);
@ -782,8 +786,8 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
void Rig::updateFromHeadParameters(const HeadParameters& params) {
updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist);
updateNeckJoint(params.neckJointIndex, params.localHeadOrientation, params.leanSideways, params.leanForward, params.torsoTwist);
updateEyeJoint(params.leftEyeJointIndex, params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
updateEyeJoint(params.rightEyeJointIndex, params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
updateEyeJoint(params.leftEyeJointIndex, params.modelTranslation, params.modelRotation, params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
updateEyeJoint(params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
}
void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist) {
@ -824,22 +828,21 @@ void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, floa
}
}
void Rig::updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade) {
void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade) {
if (index >= 0 && _jointStates[index].getParentIndex() >= 0) {
auto& state = _jointStates[index];
auto& parentState = _jointStates[state.getParentIndex()];
// NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual.
glm::mat4 inverse = glm::inverse(parentState.getTransform() *
glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) *
glm::mat4 inverse = glm::inverse(glm::mat4_cast(modelRotation) * parentState.getTransform() *
glm::translate(state.getDefaultTranslationInConstrainedFrame()) *
state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getDefaultRotation()));
glm::vec3 front = glm::vec3(inverse * glm::vec4(worldHeadOrientation * IDENTITY_FRONT, 0.0f));
glm::vec3 lookAtDelta = lookAt;
glm::vec3 lookAtDelta = lookAtSpot - modelTranslation;
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * saccade, 1.0f));
glm::quat between = rotationBetween(front, lookAt);
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
float angle = glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE);
glm::quat rot = glm::angleAxis(angle, glm::axis(between));
setJointRotationInConstrainedFrame(index, rot * state.getDefaultRotation(), DEFAULT_PRIORITY);
state.setRotationInConstrainedFrame(glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
state.getDefaultRotation(), DEFAULT_PRIORITY);
}
}

View file

@ -54,10 +54,12 @@ public:
float leanSideways = 0.0f; // degrees
float leanForward = 0.0f; // degrees
float torsoTwist = 0.0f; // degrees
glm::quat modelRotation = glm::quat();
glm::quat localHeadOrientation = glm::quat();
glm::quat worldHeadOrientation = glm::quat();
glm::vec3 eyeLookAt = glm::vec3(); // world space
glm::vec3 eyeSaccade = glm::vec3(); // world space
glm::vec3 modelTranslation = glm::vec3();
int leanJointIndex = -1;
int neckJointIndex = -1;
int leftEyeJointIndex = -1;
@ -163,7 +165,7 @@ public:
void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist);
void updateNeckJoint(int index, const glm::quat& localHeadOrientation, float leanSideways, float leanForward, float torsoTwist);
void updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade);
void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade);
QVector<JointState> _jointStates;
int _rootJointIndex = -1;

View file

@ -0,0 +1,78 @@
<!
// DeferredBufferWrite.slh
// libraries/render-utils/src
//
// Created by Sam Gateau on 1/12/15.
// 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
!>
<@if not DEFERRED_BUFFER_WRITE_SLH@>
<@def DEFERRED_BUFFER_WRITE_SLH@>
layout(location = 0) out vec4 _fragColor0;
layout(location = 1) out vec4 _fragColor1;
layout(location = 2) out vec4 _fragColor2;
// the glow intensity
uniform float glowIntensity;
// the alpha threshold
uniform float alphaThreshold;
uniform sampler2D normalFittingMap;
vec3 bestFitNormal(vec3 normal) {
vec3 absNorm = abs(normal);
float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y));
vec2 texcoord = (absNorm.z < maxNAbs ?
(absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) :
absNorm.xy);
texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy);
texcoord.y /= texcoord.x;
vec3 cN = normal / maxNAbs;
float fittingScale = texture(normalFittingMap, texcoord).a;
cN *= fittingScale;
return (cN * 0.5 + 0.5);
}
float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold));
}
const vec3 DEFAULT_SPECULAR = vec3(0.1);
const float DEFAULT_SHININESS = 10;
void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
if (alpha != glowIntensity) {
discard;
}
_fragColor0 = vec4(diffuse.rgb, alpha);
_fragColor1 = vec4(bestFitNormal(normal), 1.0);
_fragColor2 = vec4(specular, shininess / 128.0);
}
void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) {
if (alpha != glowIntensity) {
discard;
}
_fragColor0 = vec4(diffuse.rgb, alpha);
//_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
_fragColor1 = vec4(bestFitNormal(normal), 0.5);
_fragColor2 = vec4(emissive, shininess / 128.0);
}
void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) {
if (alpha <= alphaThreshold) {
discard;
}
_fragColor0 = vec4(diffuse.rgb, alpha);
// _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
// _fragColor2 = vec4(specular, shininess / 128.0);
}
<@endif@>

View file

@ -38,6 +38,7 @@
#include "RenderableZoneEntityItem.h"
#include "RenderableLineEntityItem.h"
#include "RenderablePolyVoxEntityItem.h"
#include "RenderablePolyLineEntityItem.h"
#include "EntitiesRendererLogging.h"
#include "AddressManager.h"
#include "EntityRig.h"
@ -66,6 +67,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
REGISTER_ENTITY_TYPE_WITH_FACTORY(Zone, RenderableZoneEntityItem::factory)
REGISTER_ENTITY_TYPE_WITH_FACTORY(Line, RenderableLineEntityItem::factory)
REGISTER_ENTITY_TYPE_WITH_FACTORY(PolyVox, RenderablePolyVoxEntityItem::factory)
REGISTER_ENTITY_TYPE_WITH_FACTORY(PolyLine, RenderablePolyLineEntityItem::factory)
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;

View file

@ -18,6 +18,9 @@ namespace render {
if (payload->entity->getType() == EntityTypes::Light) {
return ItemKey::Builder::light();
}
if (payload && payload->entity->getType() == EntityTypes::PolyLine) {
return ItemKey::Builder::transparentShape();
}
}
return ItemKey::Builder::opaqueShape();
}

View file

@ -35,6 +35,9 @@ void RenderableLineEntityItem::updateGeometry() {
}
}
void RenderableLineEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RenderableLineEntityItem::render");
Q_ASSERT(getType() == EntityTypes::Line);

View file

@ -275,9 +275,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
}
if (jointsMapped()) {
auto frameData = getAnimationFrame();
for (int i = 0; i < frameData.size(); i++) {
_model->setJointState(i, true, frameData[i]);
bool newFrame;
auto frameData = getAnimationFrame(newFrame);
if (newFrame) {
for (int i = 0; i < frameData.size(); i++) {
_model->setJointState(i, true, frameData[i]);
}
}
}
}

View file

@ -0,0 +1,158 @@
//
// RenderablePolyLineEntityItem.cpp
// libraries/entities-renderer/src/
//
// Created by Eric Levin on 8/10/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 <glm/gtx/quaternion.hpp>
#include <GeometryCache.h>
#include <TextureCache.h>
#include <PathUtils.h>
#include <DeferredLightingEffect.h>
#include <PerfStat.h>
#include "RenderablePolyLineEntityItem.h"
#include "paintStroke_vert.h"
#include "paintStroke_frag.h"
EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderablePolyLineEntityItem(entityID, properties));
}
RenderablePolyLineEntityItem::RenderablePolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
PolyLineEntityItem(entityItemID, properties) {
_numVertices = 0;
}
gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline;
gpu::Stream::FormatPointer RenderablePolyLineEntityItem::_format;
gpu::TexturePointer RenderablePolyLineEntityItem::_texture;
GLint RenderablePolyLineEntityItem::PAINTSTROKE_GPU_SLOT;
void RenderablePolyLineEntityItem::createPipeline() {
static const int NORMAL_OFFSET = 12;
static const int COLOR_OFFSET = 24;
static const int TEXTURE_OFFSET = 28;
auto textureCache = DependencyManager::get<TextureCache>();
QString path = PathUtils::resourcesPath() + "images/paintStroke.png";
_texture = textureCache->getImageTexture(path);
_format.reset(new gpu::Stream::Format());
_format->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
_format->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), NORMAL_OFFSET);
_format->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, COLOR_OFFSET);
_format->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), TEXTURE_OFFSET);
auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(paintStroke_vert)));
auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(paintStroke_frag)));
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));
gpu::Shader::BindingSet slotBindings;
PAINTSTROKE_GPU_SLOT = 0;
slotBindings.insert(gpu::Shader::Binding(std::string("paintStrokeTextureBinding"), PAINTSTROKE_GPU_SLOT));
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(true, true, gpu::LESS_EQUAL);
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
_pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
}
void RenderablePolyLineEntityItem::updateGeometry() {
_numVertices = 0;
_verticesBuffer.reset(new gpu::Buffer());
int vertexIndex = 0;
vec2 uv;
float tailStart = 0.0f;
float tailEnd = 0.25f;
float tailLength = tailEnd - tailStart;
float headStart = 0.76f;
float headEnd = 1.0f;
float headLength = headEnd - headStart;
float uCoord, vCoord;
int numTailStrips = 5;
int numHeadStrips = 10;
int startHeadIndex = _normals.size() - numHeadStrips;
for (int i = 0; i < _normals.size(); i++) {
uCoord = 0.26f;
vCoord = 0.0f;
//tail
if(i < numTailStrips) {
uCoord = float(i)/numTailStrips * tailLength + tailStart;
}
//head
if( i > startHeadIndex) {
uCoord = float( (i+ 1) - startHeadIndex)/numHeadStrips * headLength + headStart;
}
uv = vec2(uCoord, vCoord);
_verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_vertices.at(vertexIndex));
_verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_normals.at(i));
_verticesBuffer->append(sizeof(int), (gpu::Byte*)&_color);
_verticesBuffer->append(sizeof(glm::vec2), (gpu::Byte*)&uv);
vertexIndex++;
uv.y = 1.0f;
_verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_vertices.at(vertexIndex));
_verticesBuffer->append(sizeof(glm::vec3), (const gpu::Byte*)&_normals.at(i));
_verticesBuffer->append(sizeof(int), (gpu::Byte*)_color);
_verticesBuffer->append(sizeof(glm::vec2), (const gpu::Byte*)&uv);
vertexIndex++;
_numVertices +=2;
}
_pointsChanged = false;
}
void RenderablePolyLineEntityItem::render(RenderArgs* args) {
QWriteLocker lock(&_quadReadWriteLock);
if (_points.size() < 2 || _vertices.size() != _normals.size() * 2) {
return;
}
if (!_pipeline) {
createPipeline();
}
PerformanceTimer perfTimer("RenderablePolyLineEntityItem::render");
Q_ASSERT(getType() == EntityTypes::PolyLine);
Q_ASSERT(args->_batch);
if (_pointsChanged) {
updateGeometry();
}
gpu::Batch& batch = *args->_batch;
Transform transform = Transform();
transform.setTranslation(getPosition());
transform.setRotation(getRotation());
batch.setModelTransform(transform);
batch.setPipeline(_pipeline);
batch.setResourceTexture(PAINTSTROKE_GPU_SLOT, _texture);
batch.setInputFormat(_format);
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
RenderableDebugableEntityItem::render(this, args);
};

View file

@ -0,0 +1,47 @@
//
// RenderablePolyLineEntityItem.h
// libraries/entities-renderer/src/
//
// Created by Eric Levin on 6/22/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
//
#ifndef hifi_RenderablePolyLineEntityItem_h
#define hifi_RenderablePolyLineEntityItem_h
#include <gpu/Batch.h>
#include <PolyLineEntityItem.h>
#include "RenderableDebugableEntityItem.h"
#include "RenderableEntityItem.h"
#include <GeometryCache.h>
#include <QReadWriteLock>
#include <gpu/GPUConfig.h>
class RenderablePolyLineEntityItem : public PolyLineEntityItem {
public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static void createPipeline();
RenderablePolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
virtual void render(RenderArgs* args);
SIMPLE_RENDERABLE();
static gpu::PipelinePointer _pipeline;
static gpu::Stream::FormatPointer _format;
static gpu::TexturePointer _texture;
static GLint PAINTSTROKE_GPU_SLOT;
protected:
void updateGeometry();
gpu::BufferPointer _verticesBuffer;
unsigned int _numVertices;
};
#endif // hifi_RenderablePolyLineEntityItem_h

View file

@ -40,7 +40,7 @@
#include "EntityTreeRenderer.h"
#include "polyvox_vert.h"
#include "polyvox_frag.h"
#include "RenderablePolyVoxEntityItem.h"
#include "RenderablePolyVoxEntityItem.h"
gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr;

View file

@ -0,0 +1,45 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// paintStroke.frag
// fragment shader
//
// Created by Eric Levin on 8/10/2015
// 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 DeferredBufferWrite.slh@>
// the diffuse texture
uniform sampler2D originalTexture;
// the interpolated normal
in vec3 interpolatedNormal;
in vec2 varTexcoord;
in vec4 varColor;
float rand(vec2 point){
return fract(sin(dot(point.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main(void) {
vec4 texel = texture(originalTexture, varTexcoord);
int frontCondition = 1 -int(gl_FrontFacing) * 2;
vec3 color = varColor.rgb;
//vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess
packDeferredFragmentTranslucent(
interpolatedNormal * frontCondition,
texel.a,
color *texel.rgb,
vec3(0.01, 0.01, 0.01),
10.0);
}

View file

@ -0,0 +1,40 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// paintStroke.vert
// vertex shader
//
// Created by Eric Levin on 7/20/15.
// 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 gpu/Inputs.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
// the interpolated normal
out vec3 interpolatedNormal;
//the diffuse texture
out vec2 varTexcoord;
out vec4 varColor;
void main(void) {
varTexcoord = inTexCoord0.st;
// pass along the diffuse color
varColor = inColor;
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, interpolatedNormal)$>
}

View file

@ -28,6 +28,7 @@
#include "ZoneEntityItem.h"
#include "PolyVoxEntityItem.h"
#include "LineEntityItem.h"
#include "PolyLineEntityItem.h"
AtmospherePropertyGroup EntityItemProperties::_staticAtmosphere;
SkyboxPropertyGroup EntityItemProperties::_staticSkybox;
@ -102,6 +103,8 @@ CONSTRUCT_PROPERTY(lineWidth, LineEntityItem::DEFAULT_LINE_WIDTH),
CONSTRUCT_PROPERTY(linePoints, QVector<glm::vec3>()),
CONSTRUCT_PROPERTY(faceCamera, TextEntityItem::DEFAULT_FACE_CAMERA),
CONSTRUCT_PROPERTY(actionData, QByteArray()),
CONSTRUCT_PROPERTY(normals, QVector<glm::vec3>()),
CONSTRUCT_PROPERTY(strokeWidths, QVector<float>()),
CONSTRUCT_PROPERTY(xTextureURL, ""),
CONSTRUCT_PROPERTY(yTextureURL, ""),
CONSTRUCT_PROPERTY(zTextureURL, ""),
@ -367,6 +370,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_DESCRIPTION, description);
CHECK_PROPERTY_CHANGE(PROP_FACE_CAMERA, faceCamera);
CHECK_PROPERTY_CHANGE(PROP_ACTION_DATA, actionData);
CHECK_PROPERTY_CHANGE(PROP_NORMALS, normals);
CHECK_PROPERTY_CHANGE(PROP_STROKE_WIDTHS, strokeWidths);
CHECK_PROPERTY_CHANGE(PROP_X_TEXTURE_URL, xTextureURL);
CHECK_PROPERTY_CHANGE(PROP_Y_TEXTURE_URL, yTextureURL);
CHECK_PROPERTY_CHANGE(PROP_Z_TEXTURE_URL, zTextureURL);
@ -469,6 +474,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(description);
COPY_PROPERTY_TO_QSCRIPTVALUE(faceCamera);
COPY_PROPERTY_TO_QSCRIPTVALUE(actionData);
COPY_PROPERTY_TO_QSCRIPTVALUE(normals);
COPY_PROPERTY_TO_QSCRIPTVALUE(strokeWidths);
// Sitting properties support
if (!skipDefaults) {
@ -587,6 +594,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(description, QString, setDescription);
COPY_PROPERTY_FROM_QSCRIPTVALUE(faceCamera, bool, setFaceCamera);
COPY_PROPERTY_FROM_QSCRIPTVALUE(actionData, QByteArray, setActionData);
COPY_PROPERTY_FROM_QSCRIPTVALUE(normals, qVectorVec3, setNormals);
COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeWidths,qVectorFloat, setStrokeWidths);
if (!honorReadOnly) {
// this is used by the json reader to set things that we don't want javascript to able to affect.
@ -843,6 +852,14 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, properties.getLineWidth());
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, properties.getLinePoints());
}
if (properties.getType() == EntityTypes::PolyLine) {
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, properties.getLineWidth());
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, properties.getLinePoints());
APPEND_ENTITY_PROPERTY(PROP_NORMALS, properties.getNormals());
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, properties.getStrokeWidths());
}
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, properties.getMarketplaceID());
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
@ -1097,6 +1114,14 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_WIDTH, float, setLineWidth);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
}
if (properties.getType() == EntityTypes::PolyLine) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_WIDTH, float, setLineWidth);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NORMALS, QVector<glm::vec3>, setNormals);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
}
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
@ -1215,6 +1240,9 @@ void EntityItemProperties::markAllChanged() {
_descriptionChanged = true;
_faceCameraChanged = true;
_actionDataChanged = true;
_normalsChanged = true;
_strokeWidthsChanged = true;
_xTextureURLChanged = true;
_yTextureURLChanged = true;

View file

@ -56,6 +56,7 @@ class EntityItemProperties {
friend class WebEntityItem; // TODO: consider removing this friend relationship and use public methods
friend class LineEntityItem; // TODO: consider removing this friend relationship and use public methods
friend class PolyVoxEntityItem; // TODO: consider removing this friend relationship and use public methods
friend class PolyLineEntityItem; // TODO: consider removing this friend relationship and use public methods
public:
EntityItemProperties();
virtual ~EntityItemProperties();
@ -153,6 +154,8 @@ public:
DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString);
DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString);
DEFINE_PROPERTY(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool);
DEFINE_PROPERTY(PROP_NORMALS, Normals, normals, QVector<glm::vec3>);
DEFINE_PROPERTY(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector<float>);
DEFINE_PROPERTY_REF(PROP_ACTION_DATA, ActionData, actionData, QByteArray);
DEFINE_PROPERTY_REF(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString);
DEFINE_PROPERTY_REF(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString);

View file

@ -98,7 +98,8 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const QString& v) { ret
inline QScriptValue convertScriptValue(QScriptEngine* e, const xColor& v) { return xColorToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::quat& v) { return quatToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QScriptValue& v) { return v; }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<glm::vec3>& v) {return qVectorVec3ToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<glm::vec3>& v) {return qVectorVec3ToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<float>& v) { return qVectorFloatToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) {
QByteArray b64 = v.toBase64();
@ -134,6 +135,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) {
typedef glm::vec3 glmVec3;
typedef glm::quat glmQuat;
typedef QVector<glm::vec3> qVectorVec3;
typedef QVector<float> qVectorFloat;
inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); }
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
@ -177,6 +179,11 @@ inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isVal
return glm::vec3(0);
}
inline qVectorFloat qVectorFloat_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
return qVectorFloatFromScriptValue(v);
}
inline qVectorVec3 qVectorVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
isValid = true;
return qVectorVec3FromScriptValue(v);

View file

@ -124,11 +124,17 @@ enum EntityPropertyList {
PROP_FACE_CAMERA,
PROP_SCRIPT_TIMESTAMP,
PROP_ACTION_DATA,
PROP_X_TEXTURE_URL, // used by PolyVox
PROP_Y_TEXTURE_URL, // used by PolyVox
PROP_Z_TEXTURE_URL, // used by PolyVox
// Used by PolyLine entity
PROP_NORMALS,
PROP_STROKE_WIDTHS,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties to end of list just ABOVE this line

View file

@ -455,18 +455,18 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function<bool(Line
if (!_entityTree) {
return false;
}
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
if (!entity) {
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
}
EntityTypes::EntityType entityType = entity->getType();
if (entityType != EntityTypes::Line) {
return false;
}
auto now = usecTimestampNow();
auto lineEntity = std::static_pointer_cast<LineEntityItem>(entity);
@ -475,19 +475,20 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function<bool(Line
entity->setLastEdited(now);
entity->setLastBroadcast(now);
_entityTree->unlock();
_entityTree->lockForRead();
EntityItemProperties properties = entity->getProperties();
_entityTree->unlock();
properties.setLinePointsDirty();
properties.setLastEdited(now);
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
return success;
}
bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) {
return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) {
polyVoxEntity.setSphere(center, radius, value);
@ -507,17 +508,39 @@ bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) {
}
bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector<glm::vec3>& points) {
return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool
{
return lineEntity.setLinePoints(points);
});
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
if (!entity) {
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
}
EntityTypes::EntityType entityType = entity->getType();
if (entityType == EntityTypes::Line) {
return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool
{
return (LineEntityItem*)lineEntity.setLinePoints(points);
});
}
return false;
}
bool EntityScriptingInterface::appendPoint(QUuid entityID, const glm::vec3& point) {
return setPoints(entityID, [point](LineEntityItem& lineEntity) -> bool
{
return lineEntity.appendPoint(point);
});
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
if (!entity) {
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
}
EntityTypes::EntityType entityType = entity->getType();
if (entityType == EntityTypes::Line) {
return setPoints(entityID, [point](LineEntityItem& lineEntity) -> bool
{
return (LineEntityItem*)lineEntity.appendPoint(point);
});
}
return false;
}

View file

@ -22,6 +22,7 @@
#include <RegisteredMetaTypes.h>
#include "PolyVoxEntityItem.h"
#include "LineEntityItem.h"
#include "PolyLineEntityItem.h"
#include "EntityEditPacketSender.h"
@ -165,6 +166,7 @@ private:
bool setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor);
void queueEntityMessage(PacketType::Value packetType, EntityItemID entityID, const EntityItemProperties& properties);
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
bool precisionPicking);

View file

@ -28,6 +28,7 @@
#include "ZoneEntityItem.h"
#include "LineEntityItem.h"
#include "PolyVoxEntityItem.h"
#include "PolyLineEntityItem.h"
QMap<EntityTypes::EntityType, QString> EntityTypes::_typeToNameMap;
QMap<QString, EntityTypes::EntityType> EntityTypes::_nameToTypeMap;
@ -47,6 +48,7 @@ REGISTER_ENTITY_TYPE(ParticleEffect)
REGISTER_ENTITY_TYPE(Zone)
REGISTER_ENTITY_TYPE(Line)
REGISTER_ENTITY_TYPE(PolyVox)
REGISTER_ENTITY_TYPE(PolyLine);
const QString& EntityTypes::getEntityTypeName(EntityType entityType) {
QMap<EntityType, QString>::iterator matchedTypeName = _typeToNameMap.find(entityType);

View file

@ -47,7 +47,8 @@ public:
Web,
Line,
PolyVox,
LAST = PolyVox
PolyLine,
LAST = PolyLine
} EntityType;
static const QString& getEntityTypeName(EntityType entityType);

View file

@ -218,7 +218,8 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
}
}
const QVector<glm::quat>& ModelEntityItem::getAnimationFrame() {
const QVector<glm::quat>& ModelEntityItem::getAnimationFrame(bool& newFrame) {
newFrame = false;
if (!hasAnimation() || !_jointMappingCompleted) {
return _lastKnownFrameData;
@ -238,6 +239,7 @@ const QVector<glm::quat>& ModelEntityItem::getAnimationFrame() {
if (animationFrameIndex != _lastKnownFrameIndex) {
_lastKnownFrameIndex = animationFrameIndex;
newFrame = true;
const QVector<glm::quat>& rotations = frames[animationFrameIndex].rotations;

View file

@ -106,7 +106,7 @@ public:
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
void mapJoints(const QStringList& modelJointNames);
const QVector<glm::quat>& getAnimationFrame();
const QVector<glm::quat>& getAnimationFrame(bool& newFrame);
bool jointsMapped() const { return _jointMappingCompleted; }
bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); }

View file

@ -1,3 +1,4 @@
//
// ParticleEffectEntityItem.cpp
// libraries/entities/src

View file

@ -0,0 +1,238 @@
//
// PolyLineEntityItem.cpp
// libraries/entities/src
//
// Created by Eric Levin on 6/22/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 <QDebug>
#include <ByteCountCoding.h>
#include "PolyLineEntityItem.h"
#include "EntityTree.h"
#include "EntitiesLogging.h"
#include "EntityTreeElement.h"
#include "OctreeConstants.h"
const float PolyLineEntityItem::DEFAULT_LINE_WIDTH = 0.1f;
const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 70;
EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer result { new PolyLineEntityItem(entityID, properties) };
return result;
}
PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
EntityItem(entityItemID) ,
_lineWidth(DEFAULT_LINE_WIDTH),
_pointsChanged(true),
_points(QVector<glm::vec3>(0.0f)),
_vertices(QVector<glm::vec3>(0.0f)),
_normals(QVector<glm::vec3>(0.0f)),
_strokeWidths(QVector<float>(0.0f))
{
_type = EntityTypes::PolyLine;
_created = properties.getCreated();
setProperties(properties);
}
EntityItemProperties PolyLineEntityItem::getProperties() const {
QWriteLocker lock(&_quadReadWriteLock);
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
properties._color = getXColor();
properties._colorChanged = false;
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineWidth, getLineWidth);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(normals, getNormals);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeWidths, getStrokeWidths);
properties._glowLevel = getGlowLevel();
properties._glowLevelChanged = false;
return properties;
}
bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
QWriteLocker lock(&_quadReadWriteLock);
bool somethingChanged = false;
somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineWidth, setLineWidth);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(normals, setNormals);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeWidths, setStrokeWidths);
if (somethingChanged) {
bool wantDebug = false;
if (wantDebug) {
uint64_t now = usecTimestampNow();
int elapsed = now - getLastEdited();
qCDebug(entities) << "PolyLineEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
"now=" << now << " getLastEdited()=" << getLastEdited();
}
setLastEdited(properties._lastEdited);
}
return somethingChanged;
}
bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
if (_points.size() > MAX_POINTS_PER_LINE - 1) {
qDebug() << "MAX POINTS REACHED!";
return false;
}
glm::vec3 halfBox = getDimensions() * 0.5f;
if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) {
qDebug() << "Point is outside entity's bounding box";
return false;
}
_points << point;
_pointsChanged = true;
return true;
}
bool PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths ) {
_strokeWidths = strokeWidths;
return true;
}
bool PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
_normals = normals;
if (_points.size () < 2 || _normals.size() < 2) {
return false;
}
int minVectorSize = _normals.size();
if (_points.size() < minVectorSize) {
minVectorSize = _points.size();
}
if (_strokeWidths.size() < minVectorSize) {
minVectorSize = _strokeWidths.size();
}
_vertices.clear();
glm::vec3 v1, v2, tangent, binormal, point;
for (int i = 0; i < minVectorSize-1; i++) {
float width = _strokeWidths.at(i);
point = _points.at(i);
tangent = _points.at(i+1) - point;
glm::vec3 normal = normals.at(i);
binormal = glm::normalize(glm::cross(tangent, normal)) * width;
//This checks to make sure binormal is not a NAN
assert(binormal.x == binormal.x);
v1 = point + binormal;
v2 = point - binormal;
_vertices << v1 << v2;
}
//for last point we can just assume binormals are same since it represents last two vertices of quad
point = _points.at(_points.size() - 1);
v1 = point + binormal;
v2 = point - binormal;
_vertices << v1 << v2;
return true;
}
bool PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
if (points.size() > MAX_POINTS_PER_LINE) {
return false;
}
if (points.size() != _points.size()) {
_pointsChanged = true;
}
//Check to see if points actually changed. If they haven't, return before doing anything else
else if (points.size() == _points.size()) {
//same number of points, so now compare every point
for (int i = 0; i < points.size(); i++ ) {
if (points.at(i) != _points.at(i)){
_pointsChanged = true;
break;
}
}
}
if (!_pointsChanged) {
return false;
}
for (int i = 0; i < points.size(); i++) {
glm::vec3 point = points.at(i);
glm::vec3 pos = getPosition();
glm::vec3 halfBox = getDimensions() * 0.5f;
if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) {
qDebug() << "Point is outside entity's bounding box";
return false;
}
}
_points = points;
return true;
}
int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
QWriteLocker lock(&_quadReadWriteLock);
int bytesRead = 0;
const unsigned char* dataAt = data;
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
READ_ENTITY_PROPERTY(PROP_LINE_WIDTH, float, setLineWidth);
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
READ_ENTITY_PROPERTY(PROP_NORMALS, QVector<glm::vec3>, setNormals);
READ_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
return bytesRead;
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;
requestedProperties += PROP_LINE_WIDTH;
requestedProperties += PROP_LINE_POINTS;
requestedProperties += PROP_NORMALS;
requestedProperties += PROP_STROKE_WIDTHS;
return requestedProperties;
}
void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
QWriteLocker lock(&_quadReadWriteLock);
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, getLineWidth());
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
APPEND_ENTITY_PROPERTY(PROP_NORMALS, getNormals());
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, getStrokeWidths());
}
void PolyLineEntityItem::debugDump() const {
quint64 now = usecTimestampNow();
qCDebug(entities) << " QUAD EntityItem id:" << getEntityItemID() << "---------------------------------------------";
qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
qCDebug(entities) << " position:" << debugTreeVector(getPosition());
qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions());
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
}

View file

@ -0,0 +1,94 @@
//
// PolyLineEntityItem.h
// libraries/entities/src
//
// Created by Eric Levin on 8/3/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
//
#ifndef hifi_PolyLineEntityItem_h
#define hifi_PolyLineEntityItem_h
#include "EntityItem.h"
class PolyLineEntityItem : public EntityItem {
public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
PolyLineEntityItem(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);
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
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;
}
void setLineWidth(float lineWidth){ _lineWidth = lineWidth; }
float getLineWidth() const{ return _lineWidth; }
bool setLinePoints(const QVector<glm::vec3>& points);
bool appendPoint(const glm::vec3& point);
const QVector<glm::vec3>& getLinePoints() const{ return _points; }
bool setNormals(const QVector<glm::vec3>& normals);
const QVector<glm::vec3>& getNormals() const{ return _normals; }
bool setStrokeWidths(const QVector<float>& strokeWidths);
const QVector<float>& getStrokeWidths() const{ return _strokeWidths; }
virtual ShapeType getShapeType() const { return SHAPE_TYPE_LINE; }
// never have a ray intersection pick a PolyLineEntityItem.
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const { return false; }
virtual void debugDump() const;
static const float DEFAULT_LINE_WIDTH;
static const int MAX_POINTS_PER_LINE;
protected:
rgbColor _color;
float _lineWidth;
bool _pointsChanged;
QVector<glm::vec3> _points;
QVector<glm::vec3> _vertices;
QVector<glm::vec3> _normals;
QVector<float> _strokeWidths;
mutable QReadWriteLock _quadReadWriteLock;
};
#endif // hifi_PolyLineEntityItem_h

View file

@ -67,7 +67,7 @@ PacketVersion versionForPacketType(PacketType::Value packetType) {
case EntityAdd:
case EntityEdit:
case EntityData:
return VERSION_POLYVOX_TEXTURES;
return VERSION_ENTITIES_POLYLINE;
default:
return 11;
}

View file

@ -75,7 +75,7 @@ namespace PacketType {
EntityErase,
EntityEdit,
DomainServerConnectionToken
};
};
};
const int NUM_BYTES_MD5_HASH = 16;
@ -141,5 +141,6 @@ const PacketVersion VERSION_ENTITIES_SCRIPT_TIMESTAMP_FIX = 32;
const PacketVersion VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE = 33;
const PacketVersion VERSION_ENTITIES_NEW_PROTOCOL_LAYER = 35;
const PacketVersion VERSION_POLYVOX_TEXTURES = 36;
const PacketVersion VERSION_ENTITIES_POLYLINE = 37;
#endif // hifi_PacketHeaders_h
#endif // hifi_PacketHeaders_h

View file

@ -394,6 +394,19 @@ bool OctreePacketData::appendValue(const QVector<glm::vec3>& value) {
return success;
}
bool OctreePacketData::appendValue(const QVector<float>& value) {
uint16_t qVecSize = value.size();
bool success = appendValue(qVecSize);
if (success) {
success = append((const unsigned char*)value.constData(), qVecSize * sizeof(float));
if (success) {
_bytesOfValues += qVecSize * sizeof(float);
_totalBytesOfValues += qVecSize * sizeof(float);
}
}
return success;
}
bool OctreePacketData::appendValue(const glm::quat& value) {
const size_t VALUES_PER_QUAT = 4;
const size_t PACKED_QUAT_SIZE = sizeof(uint16_t) * VALUES_PER_QUAT;
@ -609,6 +622,16 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto
memcpy(result.data(), dataBytes, length * sizeof(glm::vec3));
return sizeof(uint16_t) + length * sizeof(glm::vec3);
}
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector<float>& result) {
uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length);
result.resize(length);
memcpy(result.data(), dataBytes, length * sizeof(float));
return sizeof(uint16_t) + length * sizeof(float);
}
int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) {
uint16_t length;
memcpy(&length, dataBytes, sizeof(length));

View file

@ -165,6 +165,9 @@ public:
//appends a QVector of vec3's to the end of the stream, may fail if new data stream is too long to fit in packet
bool appendValue(const QVector<glm::vec3>& value);
//appends a QVector of floats to the end of the stream, may fail if new data stream is too long to fit in packet
bool appendValue(const QVector<float>& value);
/// appends a packed quat to the end of the stream, may fail if new data stream is too long to fit in packet
bool appendValue(const glm::quat& value);
@ -245,6 +248,7 @@ public:
static int unpackDataFromBytes(const unsigned char* dataBytes, QUuid& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, xColor& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<glm::vec3>& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<float>& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
private:

View file

@ -139,6 +139,8 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(_ambientLightMode % gpu::SphericalHarmonics::NUM_PRESET));
}
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
bool emmisive, bool depthBias) {
SimpleProgramKey config{textured, culled, emmisive, depthBias};

View file

@ -77,6 +77,7 @@ public:
void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; }
void setGlobalSkybox(const model::SkyboxPointer& skybox);
private:
DeferredLightingEffect() {}
virtual ~DeferredLightingEffect() { }

View file

@ -19,6 +19,7 @@
#include "AbstractViewStateInterface.h"
#include "HitEffect.h"
#include "TextureCache.h"
#include "DependencyManager.h"
#include "ViewFrustum.h"
@ -43,6 +44,7 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() {
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(false, false, gpu::LESS_EQUAL);
@ -50,7 +52,7 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() {
// Blend on transparent
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
// Good to go add the brand new pipeline
_hitEffectPipeline.reset(gpu::Pipeline::create(program, state));
}
@ -77,9 +79,6 @@ void HitEffect::run(const render::SceneContextPointer& sceneContext, const rende
glm::vec2 bottomLeft(-1.0f, -1.0f);
glm::vec2 topRight(1.0f, 1.0f);
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, color);
// Ready to render
args->_context->render((batch));
}

View file

@ -26,7 +26,6 @@ public:
const gpu::PipelinePointer& getHitEffectPipeline();
private:
gpu::PipelinePointer _hitEffectPipeline;
};

View file

@ -106,6 +106,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
_drawStatusJobIndex = _jobs.size() - 1;
_jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D")));
_jobs.push_back(Job(new HitEffect::JobModel("HitEffect")));
_jobs.back().setEnabled(false);
_drawHitEffectJobIndex = _jobs.size() -1;

View file

@ -2,6 +2,7 @@
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// hit_effect.frag
// fragment shader
//
@ -12,6 +13,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DeferredBufferWrite.slh@>
in vec2 varQuadPosition;

View file

@ -33,6 +33,7 @@ void registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);
qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue);
qScriptRegisterMetaType(engine, qVectorVec3ToScriptValue, qVectorVec3FromScriptValue);
qScriptRegisterMetaType(engine, qVectorFloatToScriptValue, qVectorFloatFromScriptValue);
qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue);
qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue);
qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue);
@ -43,6 +44,7 @@ void registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue);
qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue);
qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue);
}
QScriptValue vec4toScriptValue(QScriptEngine* engine, const glm::vec4& vec4) {
@ -79,7 +81,7 @@ void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) {
vec3.z = object.property("z").toVariant().toFloat();
}
QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::vec3>& vector){
QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::vec3>& vector) {
QScriptValue array = engine->newArray();
for (int i = 0; i < vector.size(); i++) {
array.setProperty(i, vec3toScriptValue(engine, vector.at(i)));
@ -87,6 +89,39 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::
return array;
}
QVector<float> qVectorFloatFromScriptValue(const QScriptValue& array) {
if(!array.isArray()) {
return QVector<float>();
}
QVector<float> newVector;
int length = array.property("length").toInteger();
newVector.reserve(length);
for (int i = 0; i < length; i++) {
if(array.property(i).isNumber()) {
newVector << array.property(i).toNumber();
}
}
return newVector;
}
QScriptValue qVectorFloatToScriptValue(QScriptEngine* engine, const QVector<float>& vector) {
QScriptValue array = engine->newArray();
for (int i = 0; i < vector.size(); i++) {
float num = vector.at(i);
array.setProperty(i, QScriptValue(num));
}
return array;
}
void qVectorFloatFromScriptValue(const QScriptValue& array, QVector<float>& vector) {
int length = array.property("length").toInteger();
for (int i = 0; i < length; i++) {
vector << array.property(i).toVariant().toFloat();
}
}
//
QVector<glm::vec3> qVectorVec3FromScriptValue(const QScriptValue& array){
QVector<glm::vec3> newVector;
int length = array.property("length").toInteger();

View file

@ -29,6 +29,7 @@ Q_DECLARE_METATYPE(glm::vec2)
Q_DECLARE_METATYPE(glm::quat)
Q_DECLARE_METATYPE(xColor)
Q_DECLARE_METATYPE(QVector<glm::vec3>)
Q_DECLARE_METATYPE(QVector<float>)
void registerMetaTypes(QScriptEngine* engine);
@ -60,6 +61,10 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::
void qVectorVec3FromScriptValue(const QScriptValue& array, QVector<glm::vec3>& vector);
QVector<glm::vec3> qVectorVec3FromScriptValue( const QScriptValue& array);
QScriptValue qVectorFloatToScriptValue(QScriptEngine* engine, const QVector<float>& vector);
void qVectorFloatFromScriptValue(const QScriptValue& array, QVector<float>& vector);
QVector<float> qVectorFloatFromScriptValue(const QScriptValue& array);
class PickRay {
public:
PickRay() : origin(0.0f), direction(0.0f) { }

View file

@ -109,6 +109,8 @@
#include "sdf_text3D_vert.h"
#include "sdf_text3D_frag.h"
#include "paintStroke_vert.h"
#include "paintStroke_frag.h"
class RateCounter {
std::vector<float> times;
@ -324,6 +326,8 @@ void QTestWindow::draw() {
testShaderBuild(SkyFromAtmosphere_vert, SkyFromAtmosphere_frag);
testShaderBuild(Skybox_vert, Skybox_frag);
testShaderBuild(paintStroke_vert,paintStroke_frag);
});