Merge pull request #6685 from ericrius1/polylineOptimizations

First pass at Flow Arts Hut
This commit is contained in:
James B. Pollack 2015-12-22 12:28:34 -08:00
commit 88a5a0a35d
27 changed files with 1528 additions and 99 deletions

View file

@ -218,6 +218,7 @@ function getSpatialOffsetPosition(hand, spatialKey) {
}
var yFlip = Quat.angleAxis(180, Vec3.UNIT_Y);
function getSpatialOffsetRotation(hand, spatialKey) {
var rotation = Quat.IDENTITY;
@ -261,9 +262,9 @@ function MyController(hand) {
this.triggerValue = 0; // rolling average of trigger value
this.rawTriggerValue = 0;
this.rawBumperValue = 0;
this.overlayLine = null;
this.ignoreIK = false;
this.offsetPosition = Vec3.ZERO;
this.offsetRotation = Quat.IDENTITY;
@ -819,8 +820,16 @@ function MyController(hand) {
// mix in head motion
if (MOVE_WITH_HEAD) {
var objDistance = Vec3.length(objectToAvatar);
var before = Vec3.multiplyQbyV(this.currentCameraOrientation, { x: 0.0, y: 0.0, z: objDistance });
var after = Vec3.multiplyQbyV(Camera.orientation, { x: 0.0, y: 0.0, z: objDistance });
var before = Vec3.multiplyQbyV(this.currentCameraOrientation, {
x: 0.0,
y: 0.0,
z: objDistance
});
var after = Vec3.multiplyQbyV(Camera.orientation, {
x: 0.0,
y: 0.0,
z: objDistance
});
var change = Vec3.subtract(before, after);
this.currentCameraOrientation = Camera.orientation;
this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change);
@ -861,20 +870,25 @@ function MyController(hand) {
var handPosition = this.getHandPosition();
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
var objectRotation = grabbedProperties.rotation;
var currentObjectPosition = grabbedProperties.position;
var offset = Vec3.subtract(currentObjectPosition, handPosition);
if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) {
// if an object is "equipped" and has a spatialKey, use it.
this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false;
this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
if (grabbableData.spatialKey.relativePosition) {
this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
} else {
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
}
if (grabbableData.spatialKey.relativeRotation) {
this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
} else {
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
}
} else {
this.ignoreIK = false;
var objectRotation = grabbedProperties.rotation;
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
var currentObjectPosition = grabbedProperties.position;
var offset = Vec3.subtract(currentObjectPosition, handPosition);
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
}
@ -1304,10 +1318,10 @@ Controller.enableMapping(MAPPING_NAME);
var handToDisable = 'none';
function update() {
if (handToDisable !== LEFT_HAND && handToDisable!=='both') {
if (handToDisable !== LEFT_HAND && handToDisable !== 'both') {
leftController.update();
}
if (handToDisable !== RIGHT_HAND && handToDisable!=='both') {
if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') {
rightController.update();
}
}
@ -1315,7 +1329,7 @@ function update() {
Messages.subscribe('Hifi-Hand-Disabler');
handleHandDisablerMessages = function(channel, message, sender) {
if (sender === MyAvatar.sessionUUID) {
if (message === 'left') {
handToDisable = LEFT_HAND;
@ -1323,11 +1337,11 @@ handleHandDisablerMessages = function(channel, message, sender) {
if (message === 'right') {
handToDisable = RIGHT_HAND;
}
if(message==='both'){
handToDisable='both';
if (message === 'both') {
handToDisable = 'both';
}
if(message==='none'){
handToDisable='none';
if (message === 'none') {
handToDisable = 'none';
}
}
@ -1342,4 +1356,4 @@ function cleanup() {
}
Script.scriptEnding.connect(cleanup);
Script.update.connect(update);
Script.update.connect(update);

View file

@ -0,0 +1,145 @@
//
// arcBall.js
// examples/arcBall
//
// Created by Eric Levin on 12/17/15.
// Copyright 2015 High Fidelity, Inc.
//
// This script creats a particle light ball which makes particle trails as you move it.
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include("../../libraries/utils.js");
var scriptURL = Script.resolvePath("arcBallEntityScript.js?v1" + Math.random());
ArcBall = function(spawnPosition) {
var colorPalette = [{
red: 25,
green: 20,
blue: 162
}];
var containerBall = Entities.addEntity({
type: "Sphere",
name: "Arc Ball",
script: scriptURL,
position: Vec3.sum(spawnPosition, {
x: 0,
y: .7,
z: 0
}),
dimensions: {
x: .05,
y: .05,
z: .05
},
color: {
red: 100,
green: 10,
blue: 150
},
ignoreForCollisions: true,
damping: 0.8,
collisionsWillMove: true,
userData: JSON.stringify({
grabbableKey: {
spatialKey: {
// relativePosition: {
// x: 0,
// y: -0.5,
// z: 0.0
// },
},
// invertSolidWhileHeld: true
}
})
});
var light = Entities.addEntity({
type: 'Light',
name: "ballLight",
parentID: containerBall,
dimensions: {
x: 30,
y: 30,
z: 30
},
color: colorPalette[randInt(0, colorPalette.length)],
intensity: 5
});
var arcBall = Entities.addEntity({
type: "ParticleEffect",
parentID: containerBall,
isEmitting: true,
name: "Arc Ball Particle Effect",
colorStart: {
red: 200,
green: 20,
blue: 40
},
color: {
red: 200,
green: 200,
blue: 255
},
colorFinish: {
red: 25,
green: 20,
blue: 255
},
maxParticles: 100000,
lifespan: 2,
emitRate: 400,
emitSpeed: .1,
lifetime: -1,
speedSpread: 0.0,
emitDimensions: {
x: 0,
y: 0,
z: 0
},
polarStart: 0,
polarFinish: Math.PI,
azimuthStart: -Math.PI,
azimuthFinish: Math.PI,
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
accelerationSpread: {
x: .00,
y: .00,
z: .00
},
particleRadius: 0.02,
radiusSpread: 0,
radiusStart: 0.03,
radiusFinish: 0.0003,
alpha: 0,
alphaSpread: .5,
alphaStart: 0,
alphaFinish: 0.5,
textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png",
emitterShouldTrail: true
})
function cleanup() {
Entities.deleteEntity(arcBall);
Entities.deleteEntity(containerBall);
Entities.deleteEntity(light);
}
this.cleanup = cleanup;
}

View file

@ -0,0 +1,155 @@
// arcBallEntityScript.js
//
// Script Type: Entity
// Created by Eric Levin on 12/17/15.
// Copyright 2015 High Fidelity, Inc.
//
// This entity script handles the logic for the arcBall rave toy
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
(function() {
Script.include("../../libraries/utils.js");
var _this;
var ArcBall = function() {
_this = this;
this.colorPalette = [{
red: 25,
green: 20,
blue: 162
}, {
red: 200,
green: 10,
blue: 10
}];
this.searchRadius = 10;
};
ArcBall.prototype = {
isGrabbed: false,
startDistantGrab: function() {
this.searchForNearbyArcBalls();
},
startNearGrab: function() {
this.searchForNearbyArcBalls();
},
searchForNearbyArcBalls: function() {
//Search for nearby balls and create an arc to it if one is found
var position = Entities.getEntityProperties(this.entityID, "position").position
var entities = Entities.findEntities(position, this.searchRadius);
entities.forEach(function(entity) {
var props = Entities.getEntityProperties(entity, ["position", "name"]);
if (props.name === "Arc Ball" && JSON.stringify(_this.entityID) !== JSON.stringify(entity)) {
_this.target = entity;
_this.createBeam(position, props.position);
}
});
},
createBeam: function(startPosition, endPosition) {
// Creates particle arc from start position to end position
var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation;
var sourceToTargetVec = Vec3.subtract(endPosition, startPosition);
var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec);
emitOrientation = Quat.multiply(Quat.inverse(rotation), emitOrientation);
var color = this.colorPalette[randInt(0, this.colorPalette.length)];
var props = {
type: "ParticleEffect",
name: "Particle Arc",
parentID: this.entityID,
parentJointIndex: -1,
// position: startPosition,
isEmitting: true,
colorStart: color,
color: {
red: 200,
green: 200,
blue: 255
},
colorFinish: color,
maxParticles: 100000,
lifespan: 1,
emitRate: 1000,
emitOrientation: emitOrientation,
emitSpeed: 1,
speedSpread: 0.02,
emitDimensions: {
x: .01,
y: .01,
z: .01
},
polarStart: 0,
polarFinish: 0,
azimuthStart: 0.02,
azimuthFinish: .01,
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
accelerationSpread: {
x: 0,
y: 0,
z: 0
},
radiusStart: 0.01,
radiusFinish: 0.005,
radiusSpread: 0.005,
alpha: 0.5,
alphaSpread: 0.1,
alphaStart: 0.5,
alphaFinish: 0.5,
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png",
emitterShouldTrail: true
}
this.particleArc = Entities.addEntity(props);
},
updateBeam: function() {
if(!this.target) {
return;
}
var startPosition = Entities.getEntityProperties(this.entityID, "position").position;
var targetPosition = Entities.getEntityProperties(this.target, "position").position;
var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation;
var sourceToTargetVec = Vec3.subtract(targetPosition, startPosition);
var emitOrientation = Quat.rotationBetween(Vec3.UNIT_Z, sourceToTargetVec);
Entities.editEntity(this.particleArc, {
emitOrientation: emitOrientation
});
},
continueNearGrab: function() {
this.updateBeam();
},
continueDistantGrab: function() {
this.updateBeam();
},
releaseGrab: function() {
Entities.editEntity(this.particleArc, {
isEmitting: false
});
this.target = null;
},
unload: function() {
if (this.particleArc) {
Entities.deleteEntity(this.particleArc);
}
},
preload: function(entityID) {
this.entityID = entityID;
},
};
return new ArcBall();
});

View file

@ -0,0 +1,91 @@
//
// flowArtsHutSpawner.js
// examples/flowArts
//
// Created by Eric Levin on 12/17/15.
// Copyright 2015 High Fidelity, Inc.
//
// This script creates a special flow arts hut with a bunch of flow art toys people can go in and play with
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include("../../libraries/utils.js");
Script.include("lightBall/lightBall.js");
Script.include("raveStick/raveStick.js");
Script.include("lightSaber/lightSaber.js");
Script.include("arcBall/arcBall.js");
var basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation())));
basePosition.y = MyAvatar.position.y + 1;
// RAVE ITEMS
// var lightBall = new LightBall(basePosition);
var arcBall = new ArcBall(basePosition);
var arcBall2 = new ArcBall(Vec3.sum(basePosition, {x: -1, y: 0, z: 0}));
var raveStick = new RaveStick(Vec3.sum(basePosition, {x: 1, y: 0.5, z: 1}));
var lightSaber = new LightSaber(Vec3.sum(basePosition, {x: 3, y: 0.5, z: 1}));
var modelURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/RaveRoom.fbx";
var roomDimensions = {x: 30.58, y: 15.29, z: 30.58};
var raveRoom = Entities.addEntity({
type: "Model",
name: "Rave Hut Room",
modelURL: modelURL,
position: basePosition,
dimensions:roomDimensions,
visible: true
});
var floor = Entities.addEntity({
type: "Box",
name: "Rave Floor",
position: Vec3.sum(basePosition, {x: 0, y: -1.2, z: 0}),
dimensions: {x: roomDimensions.x, y: 0.6, z: roomDimensions.z},
color: {red: 50, green: 10, blue: 100},
shapeType: 'box'
});
var lightZone = Entities.addEntity({
type: "Zone",
name: "Rave Hut Zone",
shapeType: 'box',
keyLightIntensity: 0.4,
keyLightColor: {
red: 50,
green: 0,
blue: 50
},
keyLightAmbientIntensity: .2,
position: MyAvatar.position,
dimensions: {
x: 100,
y: 100,
z: 100
}
});
function cleanup() {
Entities.deleteEntity(raveRoom);
Entities.deleteEntity(lightZone);
Entities.deleteEntity(floor);
// lightBall.cleanup();
arcBall.cleanup();
arcBall2.cleanup();
raveStick.cleanup();
lightSaber.cleanup();
}
Script.scriptEnding.connect(cleanup);

View file

@ -0,0 +1,145 @@
//
// LightBall.js
// examples/lightBall
//
// Created by Eric Levin on 12/17/15.
// Copyright 2014 High Fidelity, Inc.
//
// This script creats a particle light ball which makes particle trails as you move it.
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include("../../libraries/utils.js");
LightBall = function(spawnPosition) {
var colorPalette = [{
red: 25,
green: 20,
blue: 162
}];
var containerBall = Entities.addEntity({
type: "Sphere",
name: "containerBall",
position: Vec3.sum(spawnPosition, {
x: 0,
y: 0.5,
z: 0
}),
dimensions: {
x: 0.1,
y: 0.1,
z: 0.1
},
color: {
red: 15,
green: 10,
blue: 150
},
collisionsWillMove: true,
// gravity: {
// x: 0,
// y: -0.5,
// z: 0
// },
userData: JSON.stringify({
grabbableKey: {
spatialKey: {
relativePosition: {
x: 0,
y: 0.1,
z: 0
}
},
invertSolidWhileHeld: true
}
})
});
var light = Entities.addEntity({
type: 'Light',
name: "ballLight",
parentID: containerBall,
dimensions: {
x: 30,
y: 30,
z: 30
},
color: colorPalette[randInt(0, colorPalette.length)],
intensity: 5
});
var lightBall = Entities.addEntity({
type: "ParticleEffect",
parentID: containerBall,
isEmitting: true,
name: "particleBall",
colorStart: {
red: 200,
green: 20,
blue: 40
},
color: {
red: 200,
green: 200,
blue: 255
},
colorFinish: {
red: 25,
green: 20,
blue: 255
},
maxParticles: 100000,
lifespan: 2,
emitRate: 10000,
emitSpeed: 0.1,
lifetime: -1,
speedSpread: 0.0,
emitDimensions: {
x: 0,
y: 0,
z: 0
},
polarStart: 0,
polarFinish: Math.PI,
azimuthStart: -Math.PI,
azimuthFinish: Math.PI,
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
accelerationSpread: {
x: 0.00,
y: 0.00,
z: 0.00
},
particleRadius: 0.02,
radiusSpread: 0,
radiusStart: 0.03,
radiusFinish: 0.0003,
alpha: 0,
alphaSpread: 0.5,
alphaStart: 0,
alphaFinish: 0.5,
textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png",
emitterShouldTrail: true
})
function cleanup() {
Entities.deleteEntity(lightBall);
Entities.deleteEntity(containerBall);
Entities.deleteEntity(light);
}
this.cleanup = cleanup;
}

View file

@ -0,0 +1,67 @@
//
// LightSaber.js
// examples
//
// Created by Eric Levin on 12/17/15.
// Copyright 2015 High Fidelity, Inc.
//
// This script creates a lightsaber which activates on grab
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include("../../libraries/utils.js");
var modelURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/lightSaber.fbx";
var scriptURL = Script.resolvePath("lightSaberEntityScript.js");
LightSaber = function(spawnPosition) {
var saberHandle = Entities.addEntity({
type: "Model",
name: "LightSaber Handle",
modelURL: modelURL,
position: spawnPosition,
shapeType: 'box',
collisionsWillMove: true,
script: scriptURL,
dimensions: {
x: 0.06,
y: 0.06,
z: 0.31
},
userData: JSON.stringify({
grabbableKey: {
spatialKey: {
relativePosition: {
x: 0,
y: 0,
z: -0.1
},
relativeRotation: Quat.fromPitchYawRollDegrees(180, 90, 0)
},
invertSolidWhileHeld: true
}
})
});
var light = Entities.addEntity({
type: 'Light',
name: "raveLight",
parentID: saberHandle,
dimensions: {
x: 30,
y: 30,
z: 30
},
color: {red: 200, green: 10, blue: 200},
intensity: 5
});
function cleanup() {
Entities.deleteEntity(saberHandle);
}
this.cleanup = cleanup;
}

View file

@ -0,0 +1,116 @@
// lightSaberEntityScript.js
//
// Script Type: Entity
// Created by Eric Levin on 12/17/15.
// Copyright 2015 High Fidelity, Inc.
//
// This entity script creates the logic for displaying the lightsaber beam.
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
(function() {
Script.include("../../libraries/utils.js");
var _this;
// this is the "constructor" for the entity as a JS object we don't do much here
var LightSaber = function() {
_this = this;
this.colorPalette = [{
red: 0,
green: 200,
blue: 40
}, {
red: 200,
green: 10,
blue: 40
}];
};
LightSaber.prototype = {
isGrabbed: false,
startNearGrab: function() {
Entities.editEntity(this.beam, {
isEmitting: true,
visible: true
});
},
releaseGrab: function() {
Entities.editEntity(this.beam, {
visible: false,
isEmitting: false
});
},
preload: function(entityID) {
this.entityID = entityID;
this.createBeam();
},
unload: function() {
Entities.deleteEntity(this.beam);
},
createBeam: function() {
this.props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]);
var forwardVec = Quat.getFront(Quat.multiply(this.props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0)));
var forwardQuat = Quat.rotationBetween(Vec3.UNIT_Z, forwardVec);
var position = this.props.position;
var color = this.colorPalette[randInt(0, this.colorPalette.length)];
var props = {
type: "ParticleEffect",
name: "LightSaber Beam",
position: position,
parentID: this.entityID,
isEmitting: false,
colorStart: color,
color: {
red: 200,
green: 200,
blue: 255
},
colorFinish: color,
maxParticles: 100000,
lifespan: 2,
emitRate: 1000,
emitOrientation: forwardQuat,
emitSpeed: 0.7,
speedSpread: 0.0,
emitDimensions: {
x: 0,
y: 0,
z: 0
},
polarStart: 0,
polarFinish: 0,
azimuthStart: 0.1,
azimuthFinish: 0.01,
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
accelerationSpread: {
x: .00,
y: .00,
z: .00
},
radiusStart: 0.03,
adiusFinish: 0.025,
alpha: 0.7,
alphaSpread: 0.1,
alphaStart: 0.5,
alphaFinish: 0.5,
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png",
emitterShouldTrail: false
}
this.beam = Entities.addEntity(props);
}
};
// entity scripts always need to return a newly constructed object of our type
return new LightSaber();
});

View file

@ -0,0 +1,191 @@
//
// lightTrails.js
// examples
//
// Created by Eric Levin on 5/14/15.
// Copyright 2015 High Fidelity, Inc.
//
// This script creates light trails as you move your hydra hands
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include("../libraries/utils.js");
var eraseTrail = true;
var ugLSD = 25;
// var eraseTrail = false;
var LEFT = 0;
var RIGHT = 1;
var MAX_POINTS_PER_LINE = 50;
var LIFETIME = 6000;
var DRAWING_DEPTH = 0.8;
var LINE_DIMENSIONS = 100;
var MIN_POINT_DISTANCE = 0.02;
var colorPalette = [{
red: 250,
green: 137,
blue: 162
}, {
red: 204,
green: 244,
blue: 249
}, {
red: 146,
green: 206,
blue: 116
}, {
red: 240,
green: 87,
blue: 129
}];
var STROKE_WIDTH = 0.04;
function controller(side, triggerAction) {
this.triggerHeld = false;
this.triggerThreshold = 0.9;
this.side = side;
this.triggerAction = triggerAction;
var texture = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/trails.png";
this.light = Entities.addEntity({
type: 'Light',
position: MyAvatar.position,
dimensions: {
x: 30,
y: 30,
z: 30
},
color: colorPalette[randInt(0, colorPalette.length)],
intensity: 5
});
this.trail = Entities.addEntity({
type: "PolyLine",
dimensions: {
x: LINE_DIMENSIONS,
y: LINE_DIMENSIONS,
z: LINE_DIMENSIONS
},
color: {red: 255, green: 255, blue: 255},
textures: texture,
lifetime: LIFETIME
});
this.points = [];
this.normals = [];
this.strokeWidths = [];
var self = this;
this.trailEraseInterval = Script.setInterval(function() {
if (self.points.length > 0 && eraseTrail) {
self.points.shift();
self.normals.shift();
self.strokeWidths.shift();
Entities.editEntity(self.trail, {
linePoints: self.points,
strokeWidths: self.strokeWidths,
normals: self.normals
});
}
}, ugLSD);
this.setTrailPosition = function(position) {
this.trailPosition = position;
Entities.editEntity(this.trail, {
position: this.trailPosition
});
}
this.update = function(deltaTime) {
this.updateControllerState();
var newTrailPosOffset = Vec3.multiply(Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)), DRAWING_DEPTH);
var newTrailPos = Vec3.sum(this.palmPosition, newTrailPosOffset);
Entities.editEntity(this.light, {
position: newTrailPos
});
if (!this.drawing) {
this.setTrailPosition(newTrailPos);
this.drawing = true;
}
if (this.drawing) {
var localPoint = Vec3.subtract(newTrailPos, this.trailPosition);
if (Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) {
//Need a minimum distance to avoid binormal NANs
return;
}
if (this.points.length === MAX_POINTS_PER_LINE) {
this.points.shift();
this.normals.shift();
this.strokeWidths.shift();
}
this.points.push(localPoint);
var normal = computeNormal(newTrailPos, Camera.getPosition());
this.normals.push(normal);
this.strokeWidths.push(STROKE_WIDTH + Math.random() * 0.01);
Entities.editEntity(this.trail, {
linePoints: this.points,
normals: this.normals,
strokeWidths: this.strokeWidths,
});
}
}
this.updateControllerState = function() {
this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation;
this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation;
this.triggerValue = Controller.getActionValue(this.triggerAction);
}
this.cleanup = function() {
Entities.deleteEntity(this.trail);
Entities.deleteEntity(this.light);
Script.clearInterval(this.trailEraseInterval);
}
}
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, Controller.findAction("RIGHT_HAND_CLICK"));
var leftController = new controller(LEFT, Controller.findAction("LEFT_HAND_CLICK"));
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,90 @@
//
// RaveStick.js
// examples/flowArats/raveStick
//
// Created by Eric Levin on 12/17/15.
// Copyright 2015 High Fidelity, Inc.
//
// This script creates a rave stick which makes pretty light trails as you paint
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include("../../libraries/utils.js");
var modelURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/raveStick.fbx";
var scriptURL = Script.resolvePath("raveStickEntityScript.js");
RaveStick = function(spawnPosition) {
var colorPalette = [{
red: 0,
green: 200,
blue: 40
}, {
red: 200,
green: 10,
blue: 40
}];
var stick = Entities.addEntity({
type: "Model",
name: "raveStick",
modelURL: modelURL,
position: spawnPosition,
shapeType: 'box',
collisionsWillMove: true,
script: scriptURL,
dimensions: {
x: 0.06,
y: 0.06,
z: 0.31
},
userData: JSON.stringify({
grabbableKey: {
spatialKey: {
relativePosition: {
x: 0,
y: 0,
z: -0.1
},
relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0)
},
invertSolidWhileHeld: true
}
})
});
var light = Entities.addEntity({
type: 'Light',
name: "raveLight",
parentID: stick,
dimensions: {
x: 30,
y: 30,
z: 30
},
color: colorPalette[randInt(0, colorPalette.length)],
intensity: 5
});
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0)
var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0)));
forwardVec = Vec3.normalize(forwardVec);
var forwardQuat = orientationOf(forwardVec);
var position = Vec3.sum(spawnPosition, Vec3.multiply(Quat.getFront(rotation), 0.1));
position.z += 0.1;
position.x += -0.035;
var color = {
red: 0,
green: 200,
blue: 40
};
function cleanup() {
Entities.deleteEntity(stick);
Entities.deleteEntity(light);
}
this.cleanup = cleanup;
}

View file

@ -0,0 +1,141 @@
// raveStickEntityScript.js
//
// Script Type: Entity
// Created by Eric Levin on 12/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// This entity script create light trails on a given object as it moves.
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
(function() {
Script.include("../../libraries/utils.js");
var _this;
var LIFETIME = 6000;
var DRAWING_DEPTH = 0.8;
var LINE_DIMENSIONS = 100;
var MAX_POINTS_PER_LINE = 50;
var MIN_POINT_DISTANCE = 0.02;
var STROKE_WIDTH = 0.05
var ugLSD = 35;
var RaveStick = function() {
_this = this;
this.colorPalette = [{
red: 0,
green: 200,
blue: 40
}, {
red: 200,
green: 10,
blue: 40
}];
var texture = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/trails.png";
this.trail = Entities.addEntity({
type: "PolyLine",
dimensions: {
x: LINE_DIMENSIONS,
y: LINE_DIMENSIONS,
z: LINE_DIMENSIONS
},
color: {
red: 255,
green: 255,
blue: 255
},
textures: texture,
lifetime: LIFETIME
});
this.points = [];
this.normals = [];
this.strokeWidths = [];
};
RaveStick.prototype = {
isGrabbed: false,
startNearGrab: function() {
this.trailBasePosition = Entities.getEntityProperties(this.entityID, "position").position;
Entities.editEntity(this.trail, {
position: this.trailBasePosition
});
this.points = [];
this.normals = [];
this.strokeWidths = [];
this.setupEraseInterval();
},
continueNearGrab: function() {
var props = Entities.getEntityProperties(this.entityID, ["position", "rotation"]);
var forwardVec = Quat.getFront(Quat.multiply(props.rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0)));
forwardVec = Vec3.normalize(forwardVec);
var forwardQuat = orientationOf(forwardVec);
var position = Vec3.sum(props.position, Vec3.multiply(Quat.getFront(props.rotation), 0.04));
var localPoint = Vec3.subtract(position, this.trailBasePosition);
if (this.points.length >= 1 && Vec3.distance(localPoint, this.points[this.points.length - 1]) < MIN_POINT_DISTANCE) {
//Need a minimum distance to avoid binormal NANs
return;
}
if (this.points.length === MAX_POINTS_PER_LINE) {
this.points.shift();
this.normals.shift();
this.strokeWidths.shift();
}
this.points.push(localPoint);
var normal = Quat.getUp(props.rotation);
this.normals.push(normal);
this.strokeWidths.push(STROKE_WIDTH);
Entities.editEntity(this.trail, {
linePoints: this.points,
normals: this.normals,
strokeWidths: this.strokeWidths
});
},
setupEraseInterval: function() {
this.trailEraseInterval = Script.setInterval(function() {
if (_this.points.length > 0) {
_this.points.shift();
_this.normals.shift();
_this.strokeWidths.shift();
Entities.editEntity(_this.trail, {
linePoints: _this.points,
strokeWidths: _this.strokeWidths,
normals: _this.normals
});
}
}, ugLSD);
},
releaseGrab: function() {
if(!this.trailEraseInterval) {
return;
}
Script.setTimeout(function() {
Script.clearInterval(_this.trailEraseInterval);
_this.trailEraseInterval = null;
}, 3000);
},
preload: function(entityID) {
this.entityID = entityID;
},
unload: function() {
Entities.deleteEntity(this.beam);
Entities.deleteEntity(this.trail);
if (this.trailEraseInterval) {
Script.clearInterval(this.trailEraseInterval);
}
}
};
return new RaveStick();
function computeNormal(p1, p2) {
return Vec3.normalize(Vec3.subtract(p2, p1));
}
});

View file

@ -43,6 +43,8 @@ var MAX_STROKE_WIDTH = 0.04;
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(Camera.getOrientation())));
var textureURL = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/paintStroke.png";
function MyController(hand, triggerAction) {
@ -148,7 +150,8 @@ function MyController(hand, triggerAction) {
y: 50,
z: 50
},
lifetime: 200
lifetime: 200,
textures: textureURL
});
this.strokePoints = [];
this.strokeNormals = [];

View file

@ -29,6 +29,8 @@
var MIN_STROKE_WIDTH = 0.0005;
var MAX_STROKE_WIDTH = 0.03;
var textureURL = "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/paintStroke.png";
var TRIGGER_CONTROLS = [
Controller.Standard.LT,
Controller.Standard.RT,
@ -168,6 +170,7 @@
type: "PolyLine",
name: "paintStroke",
color: this.strokeColor,
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/paintStrokes/paintStroke.png",
dimensions: {
x: 50,
y: 50,

View file

@ -38,6 +38,14 @@ var pingPongGun = Entities.addEntity({
collisionSoundURL: COLLISION_SOUND_URL,
userData: JSON.stringify({
grabbableKey: {
spatialKey: {
relativePosition: {
x: -0.05,
y: 0,
z: 0.0
},
relativeRotation: Quat.fromPitchYawRollDegrees(0, -90, -90)
},
invertSolidWhileHeld: true
}
})

View file

@ -240,8 +240,11 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
auto position = getPosition();
auto rotation = getRotation();
Transform transform;
transform.setTranslation(position);
transform.setRotation(rotation);
if (!getEmitterShouldTrail()) {
transform.setTranslation(position);
transform.setRotation(rotation);
}
render::PendingChanges pendingChanges;
pendingChanges.updateItem<ParticlePayloadData>(_renderItemId, [=](ParticlePayloadData& payload) {

View file

@ -23,6 +23,13 @@
#include "paintStroke_frag.h"
struct PolyLineUniforms {
glm::vec3 color;
};
EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer entity{ new RenderablePolyLineEntityItem(entityID) };
entity->setProperties(properties);
@ -30,9 +37,12 @@ EntityItemPointer RenderablePolyLineEntityItem::factory(const EntityItemID& enti
}
RenderablePolyLineEntityItem::RenderablePolyLineEntityItem(const EntityItemID& entityItemID) :
PolyLineEntityItem(entityItemID) {
_numVertices = 0;
PolyLineEntityItem(entityItemID),
_numVertices(0)
{
_vertices = QVector<glm::vec3>(0.0f);
PolyLineUniforms uniforms;
_uniformBuffer = std::make_shared<gpu::Buffer>(sizeof(PolyLineUniforms), (const gpu::Byte*) &uniforms);
}
gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline;
@ -41,13 +51,11 @@ int32_t 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;
static const int TEXTURE_OFFSET = 24;
_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::Shader::createVertex(std::string(paintStroke_vert));
@ -72,47 +80,28 @@ void RenderablePolyLineEntityItem::updateGeometry() {
_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 = _vertices.size() / 2 - numHeadStrips;
uCoord = 0.0f;
float uCoordInc = 1.0 / (_vertices.size() / 2);
for (int i = 0; i < _vertices.size() / 2; 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;
uCoord += uCoordInc;
}
_pointsChanged = false;
_normalsChanged = false;
@ -161,6 +150,16 @@ void RenderablePolyLineEntityItem::updateVertices() {
}
void RenderablePolyLineEntityItem::update(const quint64& now) {
PolyLineUniforms uniforms;
uniforms.color = toGlm(getXColor());
memcpy(&_uniformBuffer.edit<PolyLineUniforms>(), &uniforms, sizeof(PolyLineUniforms));
if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) {
updateVertices();
updateGeometry();
}
}
void RenderablePolyLineEntityItem::render(RenderArgs* args) {
QWriteLocker lock(&_quadReadWriteLock);
@ -181,17 +180,13 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RenderablePolyLineEntityItem::render");
Q_ASSERT(getType() == EntityTypes::PolyLine);
Q_ASSERT(args->_batch);
if (_pointsChanged || _strokeWidthsChanged || _normalsChanged) {
updateVertices();
updateGeometry();
}
gpu::Batch& batch = *args->_batch;
Transform transform = Transform();
transform.setTranslation(getPosition());
transform.setRotation(getRotation());
batch.setUniformBuffer(0, _uniformBuffer);
batch.setModelTransform(transform);
batch.setPipeline(_pipeline);
@ -200,7 +195,7 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
} else {
batch.setResourceTexture(PAINTSTROKE_GPU_SLOT, args->_whiteTexture);
}
batch.setInputFormat(_format);
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);

View file

@ -29,6 +29,8 @@ public:
RenderablePolyLineEntityItem(const EntityItemID& entityItemID);
virtual void render(RenderArgs* args);
virtual void update(const quint64& now) override;
virtual bool needsToCallUpdate() const { return true; };
SIMPLE_RENDERABLE();
@ -42,6 +44,7 @@ protected:
void updateGeometry();
void updateVertices();
gpu::BufferPointer _verticesBuffer;
gpu::BufferView _uniformBuffer;
unsigned int _numVertices;
QVector<glm::vec3> _vertices;

View file

@ -23,23 +23,24 @@ 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);
}
struct PolyLineUniforms {
vec3 color;
};
uniform polyLineBuffer {
PolyLineUniforms polyline;
};
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
vec3 color = varColor.rgb;
packDeferredFragmentTranslucent(
interpolatedNormal * frontCondition,
texel.a,
color *texel.rgb,
polyline.color * texel.rgb,
vec3(0.01, 0.01, 0.01),
10.0);
}

View file

@ -32,6 +32,7 @@ void main(void) {
// pass along the diffuse color
varColor = colorToLinearRGBA(inColor);
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();

View file

@ -195,7 +195,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_ALPHA_SPREAD, alphaSpread);
CHECK_PROPERTY_CHANGE(PROP_ALPHA_START, alphaStart);
CHECK_PROPERTY_CHANGE(PROP_ALPHA_FINISH, alphaFinish);
CHECK_PROPERTY_CHANGE(PROP_ADDITIVE_BLENDING, additiveBlending);
CHECK_PROPERTY_CHANGE(PROP_EMITTER_SHOULD_TRAIL, emitterShouldTrail);
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible);
@ -354,7 +354,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ADDITIVE_BLENDING, additiveBlending);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMITTER_SHOULD_TRAIL, emitterShouldTrail);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_POSITION, localPosition);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation);
}
@ -515,7 +515,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaSpread, float, setAlphaSpread);
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaStart, float, setAlphaStart);
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaFinish, float, setAlphaFinish);
COPY_PROPERTY_FROM_QSCRIPTVALUE(additiveBlending, bool, setAdditiveBlending);
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitterShouldTrail , bool, setEmitterShouldTrail);
COPY_PROPERTY_FROM_QSCRIPTVALUE(modelURL, QString, setModelURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL);
COPY_PROPERTY_FROM_QSCRIPTVALUE(glowLevel, float, setGlowLevel);
@ -670,7 +670,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float);
ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float);
ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float);
ADD_PROPERTY_TO_MAP(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool);
ADD_PROPERTY_TO_MAP(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool);
ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString);
ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString);
ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3);
@ -980,7 +980,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, properties.getAlphaSpread());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, properties.getAlphaStart());
APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, properties.getAlphaFinish());
APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, properties.getAdditiveBlending());
APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, properties.getEmitterShouldTrail());
}
if (properties.getType() == EntityTypes::Zone) {
@ -1265,7 +1265,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_SPREAD, float, setAlphaSpread);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_START, float, setAlphaStart);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_FINISH, float, setAlphaFinish);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail);
}
if (properties.getType() == EntityTypes::Zone) {
@ -1608,8 +1608,8 @@ QList<QString> EntityItemProperties::listChangedProperties() {
if (alphaFinishChanged()) {
out += "alphaFinish";
}
if (additiveBlendingChanged()) {
out += "additiveBlending";
if (emitterShouldTrailChanged()) {
out += "emitterShouldTrail";
}
if (modelURLChanged()) {
out += "modelURL";

View file

@ -161,7 +161,7 @@ public:
DEFINE_PROPERTY(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float, ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD);
DEFINE_PROPERTY(PROP_RADIUS_START, RadiusStart, radiusStart, float, ParticleEffectEntityItem::DEFAULT_RADIUS_START);
DEFINE_PROPERTY(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float, ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH);
DEFINE_PROPERTY(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool, ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING);
DEFINE_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool, ParticleEffectEntityItem::DEFAULT_EMITTER_SHOULD_TRAIL);
DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID);
DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup);
DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE);

View file

@ -149,7 +149,7 @@ enum EntityPropertyList {
PROP_ANIMATION_HOLD,
PROP_ANIMATION_START_AUTOMATICALLY,
PROP_ADDITIVE_BLENDING,
PROP_EMITTER_SHOULD_TRAIL,
PROP_PARENT_ID,
PROP_PARENT_JOINT_INDEX,

View file

@ -52,13 +52,13 @@ const float ParticleEffectEntityItem::MINIMUM_ALPHA = 0.0f;
const float ParticleEffectEntityItem::MAXIMUM_ALPHA = 1.0f;
const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000;
const quint32 ParticleEffectEntityItem::MINIMUM_MAX_PARTICLES = 1;
const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 10000;
const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 100000;
const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f;
const float ParticleEffectEntityItem::MINIMUM_LIFESPAN = 0.0f;
const float ParticleEffectEntityItem::MAXIMUM_LIFESPAN = 86400.0f; // 1 day
const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f;
const float ParticleEffectEntityItem::MINIMUM_EMIT_RATE = 0.0f;
const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 1000.0f;
const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 100000.0f;
const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f;
const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f;
const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3
@ -91,7 +91,7 @@ const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f;
const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS;
const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS;
const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = "";
const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false;
const bool ParticleEffectEntityItem::DEFAULT_EMITTER_SHOULD_TRAIL = false;
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
@ -331,7 +331,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaStart, getAlphaStart);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaFinish, getAlphaFinish);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(additiveBlending, getAdditiveBlending);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitterShouldTrail, getEmitterShouldTrail);
return properties;
@ -370,7 +370,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaStart, setAlphaStart);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaFinish, setAlphaFinish);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(additiveBlending, setAdditiveBlending);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitterShouldTrail, setEmitterShouldTrail);
if (somethingChanged) {
bool wantDebug = false;
@ -463,7 +463,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
}
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING) {
READ_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending);
READ_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail);
}
return bytesRead;
@ -503,7 +503,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
requestedProperties += PROP_POLAR_FINISH;
requestedProperties += PROP_AZIMUTH_START;
requestedProperties += PROP_AZIMUTH_FINISH;
requestedProperties += PROP_ADDITIVE_BLENDING;
requestedProperties += PROP_EMITTER_SHOULD_TRAIL;
return requestedProperties;
}
@ -546,7 +546,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, getPolarFinish());
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, getAzimuthStart());
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish());
APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, getAdditiveBlending());
APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, getEmitterShouldTrail());
}
bool ParticleEffectEntityItem::isEmittingParticles() const {
@ -641,13 +641,17 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() {
Particle particle;
particle.seed = randFloatInRange(0.0f, 1.0f);
particle.seed = randFloatInRange(-1.0f, 1.0f);
if (getEmitterShouldTrail()) {
particle.position = getPosition();
}
// Position, velocity, and acceleration
if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) {
// Emit along z-axis from position
particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z);
particle.velocity = (_emitSpeed + 0.2f * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z);
particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread;
} else {
@ -658,11 +662,12 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() {
float elevationMinZ = sin(PI_OVER_TWO - _polarFinish);
float elevationMaxZ = sin(PI_OVER_TWO - _polarStart);
float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat());
// float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat());
float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) *randFloat());
float azimuth;
if (_azimuthFinish >= _azimuthStart) {
azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat();
azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat();
} else {
azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat();
}
@ -693,7 +698,12 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() {
radii.z > 0.0f ? z / (radii.z * radii.z) : 0.0f
));
particle.position = _emitOrientation * emitPosition;
if (getEmitterShouldTrail()) {
particle.position += _emitOrientation * emitPosition;
}
else {
particle.position = _emitOrientation * emitPosition;
}
}
particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection);

View file

@ -213,10 +213,10 @@ public:
}
}
static const bool DEFAULT_ADDITIVE_BLENDING;
bool getAdditiveBlending() const { return _additiveBlending; }
void setAdditiveBlending(bool additiveBlending) {
_additiveBlending = additiveBlending;
static const bool DEFAULT_EMITTER_SHOULD_TRAIL;
bool getEmitterShouldTrail() const { return _emitterShouldTrail; }
void setEmitterShouldTrail(bool emitterShouldTrail) {
_emitterShouldTrail = emitterShouldTrail;
}
virtual bool supportsDetailedRayIntersection() const { return false; }
@ -286,7 +286,7 @@ protected:
float _timeUntilNextEmit { 0.0f };
bool _additiveBlending { DEFAULT_ADDITIVE_BLENDING };
bool _emitterShouldTrail { DEFAULT_EMITTER_SHOULD_TRAIL };
};
#endif // hifi_ParticleEffectEntityItem_h

View file

@ -89,6 +89,7 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
return somethingChanged;
}
bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
if (_points.size() > MAX_POINTS_PER_LINE - 1) {
qDebug() << "MAX POINTS REACHED!";
@ -104,6 +105,7 @@ bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
return true;
}
bool PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
_strokeWidths = strokeWidths;
_strokeWidthsChanged = true;

View file

@ -49,7 +49,7 @@ class PolyLineEntityItem : public EntityItem {
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;
@ -75,7 +75,9 @@ class PolyLineEntityItem : public EntityItem {
_texturesChangedFlag = true;
}
}
virtual bool needsToCallUpdate() const { return true; }
virtual ShapeType getShapeType() const { return SHAPE_TYPE_LINE; }
// never have a ray intersection pick a PolyLineEntityItem.

View file

@ -24,6 +24,7 @@
var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js");
var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js');
var bowScriptURL = Script.resolvePath('../examples/toybox/bow/bow.js');
var raveStickEntityScriptURL = Script.resolvePath("../examples/flowArts/raveStick/raveStickEntityScript.js");
var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js');
var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js');
@ -106,6 +107,13 @@
z: 505.78
});
createRaveStick({
x: 547.4,
y: 495.4,
z: 504.5
});
createCombinedArmChair({
x: 549.29,
y: 494.9,
@ -160,6 +168,111 @@
});
}
function createRaveStick(position) {
var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/raveStick.fbx";
var stick = Entities.addEntity({
type: "Model",
name: "raveStick",
modelURL: modelURL,
position: position,
shapeType: 'box',
collisionsWillMove: true,
script: raveStickEntityScriptURL,
dimensions: {
x: 0.06,
y: 0.06,
z: 0.31
},
gravity: {
x: 0,
y: -3,
z: 0
},
userData: JSON.stringify({
resetMe: {
resetMe: true
},
grabbableKey: {
spatialKey: {
relativePosition: {
x: 0,
y: 0,
z: -0.1
},
relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0)
},
invertSolidWhileHeld: true
}
})
});
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0)
var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0)));
forwardVec = Vec3.normalize(forwardVec);
var forwardQuat = orientationOf(forwardVec);
position = Vec3.sum(position, Vec3.multiply(Quat.getFront(rotation), 0.1));
position.z += 0.1;
position.x += -0.035;
var color = {
red: 0,
green: 200,
blue: 40
};
var props = {
type: "ParticleEffect",
position: position,
parentID: stick,
isEmitting: true,
name: "raveBeam",
colorStart: color,
colorSpread: {
red: 200,
green: 10,
blue: 10
},
color: {
red: 200,
green: 200,
blue: 255
},
colorFinish: color,
maxParticles: 100000,
lifespan: 1,
emitRate: 1000,
emitOrientation: forwardQuat,
emitSpeed: 0.2,
speedSpread: 0.0,
polarStart: 0,
polarFinish: 0.0,
azimuthStart: 0.1,
azimuthFinish: 0.01,
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
accelerationSpread: {
x: 0.00,
y: 0.00,
z: 0.00
},
radiusStart: 0.03,
radiusFinish: 0.025,
alpha: 0.7,
alphaSpread:0.1,
alphaStart: 0.5,
alphaFinish: 0.5,
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png",
emitterShouldTrail: false,
userData: JSON.stringify({
resetMe: {
resetMe: true
}
})
}
var beam = Entities.addEntity(props);
}
function createGun(position) {
var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/gun.fbx";
@ -1012,7 +1125,7 @@
z: 503.39
};
var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0);
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
var pingPongGun = Entities.addEntity({
type: "Model",
@ -1040,6 +1153,14 @@
resetMe: true
},
grabbableKey: {
spatialKey: {
relativePosition: {
x: -0.05,
y: 0,
z: 0.0
},
relativeRotation: Quat.fromPitchYawRollDegrees(0, -90, -90)
},
invertSolidWhileHeld: true
}

View file

@ -23,10 +23,12 @@ var wandScriptURL = Script.resolvePath("../examples/toybox/bubblewand/wand.js");
var dollScriptURL = Script.resolvePath("../examples/toybox/doll/doll.js");
var lightsScriptURL = Script.resolvePath("../examples/toybox/lights/lightSwitch.js");
var bowScriptURL = Script.resolvePath("../examples/toybox/bow/bow.js");
var raveStickEntityScriptURL = Script.resolvePath("../examples/flowArts/raveStick/raveStickEntityScript.js");
var targetsScriptURL = Script.resolvePath('../examples/toybox/ping_pong_gun/wallTarget.js');
var basketballResetterScriptURL = Script.resolvePath('basketballsResetter.js');
var targetsResetterScriptURL = Script.resolvePath('targetsResetter.js');
MasterReset = function() {
var resetKey = "resetMe";
@ -80,6 +82,12 @@ MasterReset = function() {
z: 505.78
});
createRaveStick({
x: 547.4,
y: 495.4,
z: 504.5
});
createCombinedArmChair({
@ -94,6 +102,8 @@ MasterReset = function() {
z: 504.53
});
createPingPongBallGun();
createTargets();
createTargetResetter();
@ -137,6 +147,110 @@ MasterReset = function() {
});
}
function createRaveStick(position) {
var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/rave/raveStick.fbx";
var stick = Entities.addEntity({
type: "Model",
name: "raveStick",
modelURL: modelURL,
position: position,
shapeType: 'box',
collisionsWillMove: true,
script: raveStickEntityScriptURL,
dimensions: {
x: 0.06,
y: 0.06,
z: 0.31
},
gravity: {
x: 0,
y: -3,
z: 0
},
userData: JSON.stringify({
resetMe: {
resetMe: true
},
grabbableKey: {
spatialKey: {
relativePosition: {
x: 0,
y: 0,
z: -0.1
},
relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0)
},
invertSolidWhileHeld: true
}
})
});
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0)
var forwardVec = Quat.getFront(Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(-90, 0, 0)));
forwardVec = Vec3.normalize(forwardVec);
var forwardQuat = orientationOf(forwardVec);
position = Vec3.sum(position, Vec3.multiply(Quat.getFront(rotation), 0.1));
position.z += 0.1;
position.x += -0.035;
var color = {
red: 0,
green: 200,
blue: 40
};
var props = {
type: "ParticleEffect",
position: position,
parentID: stick,
isEmitting: true,
name: "raveBeam",
colorStart: color,
colorSpread: {
red: 200,
green: 10,
blue: 10
},
color: {
red: 200,
green: 200,
blue: 255
},
colorFinish: color,
maxParticles: 100000,
lifespan: 1,
emitRate: 1000,
emitOrientation: forwardQuat,
emitSpeed: 0.2,
speedSpread: 0.0,
polarStart: 0,
polarFinish: 0.0,
azimuthStart: 0.1,
azimuthFinish: 0.01,
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
accelerationSpread: {
x: 0.00,
y: 0.00,
z: 0.00
},
radiusStart: 0.03,
radiusFinish: 0.025,
alpha: 0.7,
alphaSpread: 0.1,
alphaStart: 0.5,
alphaFinish: 0.5,
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png",
emitterShouldTrail: false,
userData: JSON.stringify({
resetMe: {
resetMe: true
}
})
}
var beam = Entities.addEntity(props);
}
function createGun(position) {
var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/gun.fbx";
@ -992,7 +1106,7 @@ MasterReset = function() {
z: 503.39
};
var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0);
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
var pingPongGun = Entities.addEntity({
type: "Model",
@ -1020,6 +1134,14 @@ MasterReset = function() {
resetMe: true
},
grabbableKey: {
spatialKey: {
relativePosition: {
x: -0.05,
y: 0,
z: 0.0
},
relativeRotation: Quat.fromPitchYawRollDegrees(0,-90, -90)
},
invertSolidWhileHeld: true
}
@ -1349,7 +1471,7 @@ MasterReset = function() {
resetMe: true
},
grabbableKey: {
invertSolidWhileHeld: true
invertSolidWhileHeld: true
}
})
});