mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-16 09:20:12 +02:00
Merge branch 'physics-ccd' of https://github.com/huffman/hifi
Conflicts: examples/libraries/walkApi.js examples/toybox/flashlight/flashlight.js examples/walk.js
This commit is contained in:
commit
0ea2ca589b
9 changed files with 852 additions and 1 deletions
23
examples/baseball/audio/assets.txt
Normal file
23
examples/baseball/audio/assets.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
crowd-boos.wav
|
||||
atp:c632c92b166ade60aa16b23ff1dfdf712856caeb83bd9311980b2d5edac821af.wav
|
||||
|
||||
crowd-cheers-organ.wav
|
||||
atp:b8044401a846ed29f881a0b9b80cf1ba41f26327180c28fc9c70d144f9b70045.wav
|
||||
|
||||
crowd-medium.wav
|
||||
atp:0821bf2ac60dd2f356dfdd948e8bb89c23984dc3584612f6c815765154f02cae.wav
|
||||
|
||||
baseball-hitting-bat-1.wav
|
||||
atp:6f0b691a0c9c9ece6557d97fe242b1faec4020fe26efc9c17327993b513c5fe5.wav
|
||||
|
||||
baseball-hitting-bat-set-1.wav
|
||||
atp:5be5806205158ebdc5c3623ceb7ae73315028b51ffeae24292aff7042e3fa6a9.wav
|
||||
|
||||
baseball-hitting-bat-set-2.wav
|
||||
atp:e68661374e2145c480809c26134782aad11e0de456c7802170c7abccc4028873.wav
|
||||
|
||||
baseball-hitting-bat-set-3.wav
|
||||
atp:787e3c9af17dd3929527787176ede83d6806260e63ddd5a4cef48cd22e32c6f7.wav
|
||||
|
||||
baseball-hitting-bat-set-4.wav
|
||||
atp:fc65383431a6238c7a4749f0f6f061f75a604ed5e17d775ab1b2955609e67ebb.wav
|
8
examples/baseball/audio/attribution.txt
Normal file
8
examples/baseball/audio/attribution.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Baseball bat hitting sounds
|
||||
https://www.freesound.org/people/SocializedArtist45/sounds/266595/
|
||||
https://www.freesound.org/people/CGEffex/sounds/93136/
|
||||
|
||||
Crowd Sounds
|
||||
http://freesound.org/people/AshFox/sounds/191925/
|
||||
http://freesound.org/people/AshFox/sounds/191928/
|
||||
http://freesound.org/people/AshFox/sounds/191929/
|
165
examples/baseball/line.js
Normal file
165
examples/baseball/line.js
Normal file
|
@ -0,0 +1,165 @@
|
|||
function info(message) {
|
||||
print("[INFO] " + message);
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
print("[ERROR] " + message);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* PolyLine
|
||||
*****************************************************************************/
|
||||
var LINE_DIMENSIONS = { x: 2000, y: 2000, z: 2000 };
|
||||
var MAX_LINE_LENGTH = 40; // This must be 2 or greater;
|
||||
var PolyLine = function(position, color, defaultStrokeWidth) {
|
||||
//info("Creating polyline");
|
||||
//Vec3.print("New line at", position);
|
||||
this.position = position;
|
||||
this.color = color;
|
||||
this.defaultStrokeWidth = 0.10;
|
||||
this.points = [
|
||||
{ x: 0, y: 0, z: 0 },
|
||||
];
|
||||
this.strokeWidths = [
|
||||
this.defaultStrokeWidth,
|
||||
]
|
||||
this.normals = [
|
||||
{ x: 1, y: 0, z: 0 },
|
||||
]
|
||||
this.entityID = Entities.addEntity({
|
||||
type: "PolyLine",
|
||||
position: position,
|
||||
linePoints: this.points,
|
||||
normals: this.normals,
|
||||
strokeWidths: this.strokeWidths,
|
||||
dimensions: LINE_DIMENSIONS,
|
||||
color: color,
|
||||
lifetime: 20,
|
||||
});
|
||||
};
|
||||
|
||||
PolyLine.prototype.enqueuePoint = function(position) {
|
||||
if (this.isFull()) {
|
||||
error("Hit max PolyLine size");
|
||||
return;
|
||||
}
|
||||
|
||||
//Vec3.print("pos", position);
|
||||
//info("Number of points: " + this.points.length);
|
||||
|
||||
position = Vec3.subtract(position, this.position);
|
||||
this.points.push(position);
|
||||
this.normals.push({ x: 1, y: 0, z: 0 });
|
||||
this.strokeWidths.push(this.defaultStrokeWidth);
|
||||
Entities.editEntity(this.entityID, {
|
||||
linePoints: this.points,
|
||||
normals: this.normals,
|
||||
strokeWidths: this.strokeWidths,
|
||||
});
|
||||
};
|
||||
|
||||
PolyLine.prototype.dequeuePoint = function() {
|
||||
if (this.points.length == 0) {
|
||||
error("Hit min PolyLine size");
|
||||
return;
|
||||
}
|
||||
|
||||
this.points = this.points.slice(1);
|
||||
this.normals = this.normals.slice(1);
|
||||
this.strokeWidths = this.strokeWidths.slice(1);
|
||||
|
||||
Entities.editEntity(this.entityID, {
|
||||
linePoints: this.points,
|
||||
normals: this.normals,
|
||||
strokeWidths: this.strokeWidths,
|
||||
});
|
||||
};
|
||||
|
||||
PolyLine.prototype.getFirstPoint = function() {
|
||||
return Vec3.sum(this.position, this.points[0]);
|
||||
};
|
||||
|
||||
PolyLine.prototype.getLastPoint = function() {
|
||||
return Vec3.sum(this.position, this.points[this.points.length - 1]);
|
||||
};
|
||||
|
||||
PolyLine.prototype.getSize = function() {
|
||||
return this.points.length;
|
||||
}
|
||||
|
||||
PolyLine.prototype.isFull = function() {
|
||||
return this.points.length >= MAX_LINE_LENGTH;
|
||||
};
|
||||
|
||||
PolyLine.prototype.destroy = function() {
|
||||
Entities.deleteEntity(this.entityID);
|
||||
this.points = [];
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* InfiniteLine
|
||||
*****************************************************************************/
|
||||
InfiniteLine = function(position, color) {
|
||||
this.position = position;
|
||||
this.color = color;
|
||||
this.lines = [new PolyLine(position, color)];
|
||||
this.size = 0;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.enqueuePoint = function(position) {
|
||||
var currentLine;
|
||||
|
||||
if (this.lines.length == 0) {
|
||||
currentLine = new PolyLine(position, this.color);
|
||||
this.lines.push(currentLine);
|
||||
} else {
|
||||
currentLine = this.lines[this.lines.length - 1];
|
||||
}
|
||||
|
||||
if (currentLine.isFull()) {
|
||||
//info("Current line is full, creating new line");
|
||||
//Vec3.print("Last line is", currentLine.getLastPoint());
|
||||
//Vec3.print("New line is", position);
|
||||
var newLine = new PolyLine(currentLine.getLastPoint(), this.color);
|
||||
this.lines.push(newLine);
|
||||
currentLine = newLine;
|
||||
}
|
||||
|
||||
currentLine.enqueuePoint(position);
|
||||
|
||||
++this.size;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.dequeuePoint = function() {
|
||||
if (this.lines.length == 0) {
|
||||
error("Trying to dequeue from InfiniteLine when no points are left");
|
||||
return;
|
||||
}
|
||||
|
||||
var lastLine = this.lines[0];
|
||||
lastLine.dequeuePoint();
|
||||
|
||||
if (lastLine.getSize() <= 1) {
|
||||
this.lines = this.lines.slice(1);
|
||||
}
|
||||
|
||||
--this.size;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.getFirstPoint = function() {
|
||||
return this.lines.length > 0 ? this.lines[0].getFirstPoint() : null;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.getLastPoint = function() {
|
||||
return this.lines.length > 0 ? this.lines[lines.length - 1].getLastPoint() : null;
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.destroy = function() {
|
||||
for (var i = 0; i < this.lines.length; ++i) {
|
||||
this.lines[i].destroy();
|
||||
}
|
||||
|
||||
this.size = 0;
|
||||
};
|
313
examples/baseball/pitching.js
Normal file
313
examples/baseball/pitching.js
Normal file
|
@ -0,0 +1,313 @@
|
|||
Script.include("line.js");
|
||||
|
||||
var AUDIO = {
|
||||
crowdBoos: [
|
||||
SoundCache.getSound("atp:c632c92b166ade60aa16b23ff1dfdf712856caeb83bd9311980b2d5edac821af.wav", false)
|
||||
],
|
||||
crowdCheers: [
|
||||
SoundCache.getSound("atp:0821bf2ac60dd2f356dfdd948e8bb89c23984dc3584612f6c815765154f02cae.wav", false),
|
||||
SoundCache.getSound("atp:b8044401a846ed29f881a0b9b80cf1ba41f26327180c28fc9c70d144f9b70045.wav", false),
|
||||
],
|
||||
batHit: [
|
||||
SoundCache.getSound("atp:6f0b691a0c9c9ece6557d97fe242b1faec4020fe26efc9c17327993b513c5fe5.wav", false),
|
||||
SoundCache.getSound("atp:5be5806205158ebdc5c3623ceb7ae73315028b51ffeae24292aff7042e3fa6a9.wav", false),
|
||||
SoundCache.getSound("atp:e68661374e2145c480809c26134782aad11e0de456c7802170c7abccc4028873.wav", false),
|
||||
SoundCache.getSound("atp:787e3c9af17dd3929527787176ede83d6806260e63ddd5a4cef48cd22e32c6f7.wav", false),
|
||||
SoundCache.getSound("atp:fc65383431a6238c7a4749f0f6f061f75a604ed5e17d775ab1b2955609e67ebb.wav", false),
|
||||
]
|
||||
}
|
||||
|
||||
var PITCH_THUNK_SOUND_URL = "http://hifi-public.s3.amazonaws.com/sounds/ping_pong_gun/pong_sound.wav";
|
||||
var pitchSound = SoundCache.getSound(PITCH_THUNK_SOUND_URL, false);
|
||||
|
||||
var PITCHING_MACHINE_URL = "atp:87d4879530b698741ecc45f6f31789aac11f7865a2c3bec5fe9b061a182c80d4.fbx";
|
||||
var PITCHING_MACHINE_OUTPUT_OFFSET_PCT = {
|
||||
x: 0.0,
|
||||
y: 0.25,
|
||||
z: -1.05,
|
||||
};
|
||||
var PITCHING_MACHINE_PROPERTIES = {
|
||||
name: "Pitching Machine",
|
||||
type: "Model",
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0.8,
|
||||
z: -18.3,
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
},
|
||||
gravity: {
|
||||
x: 0.0,
|
||||
y: -9.8,
|
||||
z: 0.0
|
||||
},
|
||||
registrationPoint: {
|
||||
x: 0.5,
|
||||
y: 0.5,
|
||||
z: 0.5,
|
||||
},
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 180, 0),
|
||||
modelURL: PITCHING_MACHINE_URL,
|
||||
dimensions: {
|
||||
x: 0.4,
|
||||
y: 0.61,
|
||||
z: 0.39
|
||||
},
|
||||
collisionsWillMove: false,
|
||||
shapeType: "Box",
|
||||
};
|
||||
PITCHING_MACHINE_PROPERTIES.dimensions = Vec3.multiply(2.5, PITCHING_MACHINE_PROPERTIES.dimensions);
|
||||
var DISTANCE_FROM_PLATE = PITCHING_MACHINE_PROPERTIES.position.z;
|
||||
|
||||
var PITCH_RATE = 5000;
|
||||
|
||||
var BASEBALL_MODEL_URL = "atp:7185099f1f650600ca187222573a88200aeb835454bd2f578f12c7fb4fd190fa.fbx";
|
||||
var BASEBALL_MIN_SPEED = 2.7;
|
||||
var BASEBALL_MAX_SPEED = 5.7;
|
||||
var BASEBALL_RADIUS = 0.07468;
|
||||
var BASEBALL_PROPERTIES = {
|
||||
name: "Baseball",
|
||||
type: "Model",
|
||||
modelURL: BASEBALL_MODEL_URL,
|
||||
shapeType: "Sphere",
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
dimensions: {
|
||||
x: BASEBALL_RADIUS,
|
||||
y: BASEBALL_RADIUS,
|
||||
z: BASEBALL_RADIUS
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
angularVelocity: {
|
||||
x: 17.0,
|
||||
y: 0,
|
||||
z: -8.0,
|
||||
|
||||
x: 0.0,
|
||||
y: 0,
|
||||
z: 0.0,
|
||||
},
|
||||
angularDamping: 0.0,
|
||||
damping: 0.0,
|
||||
restitution: 0.5,
|
||||
friction: 0.0,
|
||||
lifetime: 20,
|
||||
//collisionSoundURL: PITCH_THUNK_SOUND_URL,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: 0,//-9.8,
|
||||
z: 0
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var pitchingMachineID = Entities.addEntity(PITCHING_MACHINE_PROPERTIES);
|
||||
|
||||
var pitchFromPosition = { x: 0, y: 1.0, z: 0 };
|
||||
var pitchDirection = { x: 0, y: 0, z: 1 };
|
||||
|
||||
function shallowCopy(obj) {
|
||||
var copy = {}
|
||||
for (var key in obj) {
|
||||
copy[key] = obj[key];
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
function randomInt(low, high) {
|
||||
return Math.floor(randomFloat(low, high));
|
||||
}
|
||||
|
||||
function randomFloat(low, high) {
|
||||
if (high === undefined) {
|
||||
high = low;
|
||||
low = 0;
|
||||
}
|
||||
return low + Math.random() * (high - low);
|
||||
}
|
||||
|
||||
var ACCELERATION_SPREAD = 10.15;
|
||||
|
||||
function Baseball(position, velocity, ballScale) {
|
||||
var self = this;
|
||||
|
||||
// Setup entity properties
|
||||
var properties = shallowCopy(BASEBALL_PROPERTIES);
|
||||
properties.position = position;
|
||||
properties.velocity = velocity;
|
||||
/*
|
||||
properties.gravity = {
|
||||
x: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
y: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
z: 0.0,
|
||||
};
|
||||
*/
|
||||
properties.dimensions = Vec3.multiply(ballScale, properties.dimensions);
|
||||
|
||||
// Create entity
|
||||
this.entityID = Entities.addEntity(properties);
|
||||
this.trail = null;
|
||||
this.onHit = function() { return true; };
|
||||
this.hasBeenHit = false;
|
||||
|
||||
this.boundCollisionCallback = function(a, b, c) { self.collisionCallback.call(self, a, b, c); };
|
||||
Script.addEventHandler(this.entityID, "collisionWithEntity", this.boundCollisionCallback);
|
||||
/*
|
||||
if (false && Math.random() < 0.5) {
|
||||
for (var i = 0; i < 50; i++) {
|
||||
Script.setTimeout(function() {
|
||||
Entities.editEntity(entityID, {
|
||||
gravity: {
|
||||
x: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
y: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD),
|
||||
z: 0.0,
|
||||
}
|
||||
})
|
||||
}, i * 100);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Baseball.prototype = {
|
||||
collisionCallback: function(entityA, entityB, collision) {
|
||||
var self = this;
|
||||
|
||||
this.hasBeenHit = true;
|
||||
var properties = Entities.getEntityProperties(this.entityID, ['position', 'velocity']);
|
||||
this.trail = new InfiniteLine(properties.position, { red: 255, green: 128, blue: 89 });
|
||||
var lastPosition = properties.position;
|
||||
//Vec3.print("Velocity", properties.velocity);
|
||||
//Vec3.print("VelocityChange", collision.velocityChange);
|
||||
var speed = Vec3.length(properties.velocity);
|
||||
playRandomSound(AUDIO.batHit, {
|
||||
position: properties.position,
|
||||
volume: 2.0
|
||||
});
|
||||
var sounds = null;
|
||||
if (speed < 5.0) {
|
||||
sounds = AUDIO.crowdBoos;
|
||||
} else {
|
||||
sounds = AUDIO.crowdCheers;
|
||||
}
|
||||
var self = this;
|
||||
this.trailInterval = Script.setInterval(function() {
|
||||
var properties = Entities.getEntityProperties(self.entityID, ['position']);
|
||||
if (Vec3.distance(properties.position, lastPosition)) {
|
||||
self.trail.enqueuePoint(properties.position);
|
||||
lastPosition = properties.position;
|
||||
}
|
||||
}, 50);
|
||||
Entities.editEntity(self.entityID, {
|
||||
velocity: Vec3.multiply(2, properties.velocity),
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -9.8,
|
||||
z: 0
|
||||
}
|
||||
});
|
||||
|
||||
var removeHandler = this.onHit(entityB, collision);
|
||||
if (removeHandler) {
|
||||
Script.removeEventHandler(self.entityID, "collisionWithEntity", self.boundCollisionCallback);
|
||||
}
|
||||
},
|
||||
cleanupTrail: function() {
|
||||
if (this.trail) {
|
||||
Script.clearInterval(this.trailInterval);
|
||||
this.trailInterval = null;
|
||||
|
||||
this.trail.destroy();
|
||||
this.trail = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function playRandomSound(sounds, options) {
|
||||
if (options === undefined) {
|
||||
options = {
|
||||
volume: 1.0,
|
||||
position: MyAvatar.position,
|
||||
}
|
||||
}
|
||||
Audio.playSound(sounds[randomInt(sounds.length)], options);
|
||||
}
|
||||
|
||||
var lastTrail = null;
|
||||
|
||||
|
||||
function vec3Mult(a, b) {
|
||||
return {
|
||||
x: a.x * b.x,
|
||||
y: a.y * b.y,
|
||||
z: a.z * b.z,
|
||||
};
|
||||
}
|
||||
|
||||
var lastBall = null;
|
||||
var injector = null;
|
||||
|
||||
function pitchBall() {
|
||||
if (lastBall) {
|
||||
lastBall.cleanupTrail();
|
||||
}
|
||||
|
||||
var machineProperties = Entities.getEntityProperties(pitchingMachineID, ["dimensions", "position", "rotation"]);
|
||||
var pitchFromPositionBase = machineProperties.position;
|
||||
var pitchFromOffset = vec3Mult(machineProperties.dimensions, PITCHING_MACHINE_OUTPUT_OFFSET_PCT);
|
||||
pitchFromOffset = Vec3.multiplyQbyV(machineProperties.rotation, pitchFromOffset);
|
||||
var pitchFromPosition = Vec3.sum(pitchFromPositionBase, pitchFromOffset);
|
||||
var pitchDirection = Quat.getFront(machineProperties.rotation);
|
||||
var ballScale = machineProperties.dimensions.x / PITCHING_MACHINE_PROPERTIES.dimensions.x;
|
||||
print("Creating baseball");
|
||||
|
||||
var speed = randomFloat(BASEBALL_MIN_SPEED, BASEBALL_MAX_SPEED)
|
||||
var timeToPassPlate = (DISTANCE_FROM_PLATE + 1.0) / speed;
|
||||
|
||||
var baseball = new Baseball(pitchFromPosition, Vec3.multiply(speed, pitchDirection), ballScale);
|
||||
lastBall = baseball;
|
||||
|
||||
baseball.onHit = function(entityB, collision) {
|
||||
var properties = Entities.getEntityProperties(entityB, ["name"]);
|
||||
var name = properties.name;
|
||||
print("Hit: " + name);
|
||||
if (name == "backstop") {
|
||||
print("STRIKE");
|
||||
} else if (name == "bat") {
|
||||
print("HIT");
|
||||
Script.setTimeout(function() {
|
||||
playRandomSound(sounds, {
|
||||
position: { x: 0 ,y: 0, z: 0 },
|
||||
volume: 1.0,
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
//Script.clearTimeout(strikeTimeout);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!injector) {
|
||||
injector = Audio.playSound(pitchSound, {
|
||||
position: pitchFromPosition,
|
||||
volume: 1.0
|
||||
});
|
||||
} else {
|
||||
injector.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(function() {
|
||||
Entities.deleteEntity(pitchingMachineID);
|
||||
})
|
||||
|
||||
Script.setInterval(pitchBall, PITCH_RATE);
|
||||
|
||||
|
||||
|
||||
|
0
examples/baseballEntityScript.js
Normal file
0
examples/baseballEntityScript.js
Normal file
323
examples/map.js~
Normal file
323
examples/map.js~
Normal file
|
@ -0,0 +1,323 @@
|
|||
Script.include("entityManager.js");
|
||||
Script.include("overlayManager.js");
|
||||
|
||||
|
||||
// Poll for nearby map data
|
||||
|
||||
var entityManager = new EntityManager();
|
||||
|
||||
// From http://evanw.github.io/lightgl.js/docs/raytracer.html
|
||||
function raySphereIntersection(origin, ray, center, radius) {
|
||||
var offset = Vec3.subtract(origin, center);
|
||||
var a = Vec3.dot(ray, ray);
|
||||
// var a = ray.dot(ray);
|
||||
var b = 2 * Vec3.dot(ray, offset);
|
||||
// var b = 2 * ray.dot(offset);
|
||||
var c = Vec3.dot(offset, offset) - radius * radius;
|
||||
// var c = offset.dot(offset) - radius * radius;
|
||||
var discriminant = b * b - 4 * a * c;
|
||||
|
||||
if (discriminant > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
Map = function(data) {
|
||||
var visible = false;
|
||||
|
||||
var ROOT_OFFSET = Vec3.multiply(0.3, Quat.getFront(MyAvatar.orientation));
|
||||
var ROOT_POSITION = Vec3.sum(MyAvatar.position, ROOT_OFFSET);
|
||||
|
||||
var ROOT_SCALE = 0.0005;
|
||||
|
||||
// Create object in objectManager
|
||||
var rootObject = entityManager.addBare();
|
||||
var position = ROOT_POSITION;
|
||||
rootObject.position = ROOT_POSITION;
|
||||
rootObject.scale = ROOT_SCALE
|
||||
Vec3.print("Position:", position);
|
||||
|
||||
// Search for all nearby objects that have the userData "mapped"
|
||||
// TODO Update to use the zone's bounds
|
||||
var entities = Entities.findEntities(MyAvatar.position, 32000);
|
||||
var mappedEntities = [];
|
||||
var minCorner = {
|
||||
x: 4294967295,
|
||||
y: 4294967295,
|
||||
z: 4294967295,
|
||||
};
|
||||
var maxCorner = {
|
||||
x: -4294967295,
|
||||
y: -4294967295,
|
||||
z: -4294967295,
|
||||
};
|
||||
|
||||
for (var i = 0; i < entities.length; ++i) {
|
||||
var entityID = entities[i];
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
if (properties.userData == "mapped" || properties.userData == "tracked") {
|
||||
|
||||
print("Found: ", properties.name);
|
||||
|
||||
minCorner.x = Math.min(minCorner.x, properties.position.x - (properties.dimensions.x / 2));
|
||||
minCorner.y = Math.min(minCorner.y, properties.position.y - (properties.dimensions.y / 2));
|
||||
minCorner.z = Math.min(minCorner.z, properties.position.z - (properties.dimensions.z / 2));
|
||||
|
||||
maxCorner.x = Math.max(maxCorner.x, properties.position.x - (properties.dimensions.x / 2));
|
||||
maxCorner.y = Math.max(maxCorner.y, properties.position.y - (properties.dimensions.y / 2));
|
||||
maxCorner.z = Math.max(maxCorner.z, properties.position.z - (properties.dimensions.z / 2));
|
||||
|
||||
}
|
||||
// if (properties.userData == "mapped") {
|
||||
// properties.visible = false;
|
||||
// var entity = entityManager.add(properties.type, properties);
|
||||
// mappedEntities.push(entity);
|
||||
// } else if (properties.userData == "tracked") {
|
||||
// // TODO implement tracking of objects
|
||||
// }
|
||||
}
|
||||
|
||||
var dimensions = {
|
||||
x: maxCorner.x - minCorner.x,
|
||||
y: maxCorner.y - minCorner.y,
|
||||
z: maxCorner.z - minCorner.z,
|
||||
};
|
||||
Vec3.print("dims", dimensions);
|
||||
|
||||
var center = {
|
||||
x: minCorner.x + (dimensions.x / 2),
|
||||
y: minCorner.y + (dimensions.y / 2),
|
||||
z: minCorner.z + (dimensions.z / 2),
|
||||
};
|
||||
Vec3.print("center", center);
|
||||
|
||||
var trackedEntities = [];
|
||||
var waypointEntities = [];
|
||||
for (var i = 0; i < entities.length; ++i) {
|
||||
var entityID = entities[i];
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
var mapData = null;
|
||||
try {
|
||||
var data = JSON.parse(properties.userData.replace(/(\r\n|\n|\r)/gm,""));
|
||||
mapData = data.mapData;
|
||||
} catch (e) {
|
||||
print("Caught: ", properties.name);
|
||||
}
|
||||
|
||||
if (mapData) {
|
||||
print("Creating copy of", properties.name);
|
||||
properties.name += " (COPY)";
|
||||
properties.userData = "";
|
||||
properties.visible = true;
|
||||
var position = properties.position;
|
||||
properties.position = Vec3.subtract(properties.position, center);
|
||||
properties.position = Vec3.multiply(properties.position, ROOT_SCALE);
|
||||
var extra = { };
|
||||
|
||||
if (mapData.track) {
|
||||
extra.trackingEntityID= entityID;
|
||||
trackedEntities.push(entity);
|
||||
rootObject.addChild(entity);
|
||||
}
|
||||
if (mapData.waypoint) {
|
||||
print("Waypoint: ", mapData.waypoint.name);
|
||||
// properties.type = "Model";
|
||||
// properties.modelURL = "atp:ca49a13938376b3eb68d7b2b9189afb3f580c07b6950ea9e65b5260787204145.fbx";
|
||||
extra.waypoint = mapData.waypoint;
|
||||
extra.waypoint.position = position;
|
||||
}
|
||||
|
||||
var entity = entityManager.add(properties.type, properties);
|
||||
entity.__extra__ = extra;
|
||||
if (mapData.waypoint) {
|
||||
waypointEntities.push(entity);
|
||||
}
|
||||
mappedEntities.push(entity);
|
||||
|
||||
rootObject.addChild(entity);
|
||||
|
||||
} else {
|
||||
// print("Not creating copy of", properties.name);
|
||||
}
|
||||
}
|
||||
|
||||
var avatarArrowEntity = entityManager.add("Model", {
|
||||
name: "You Are Here",
|
||||
modelURL: "atp:ce4f0c4e491e40b73d28f2646da4f676fe9ea364cf5f1bf5615522ef6acfd80e.fbx",
|
||||
position: Vec3.multiply(Vec3.subtract(MyAvatar.position, center), ROOT_SCALE),
|
||||
dimensions: { x: 30, y: 100, z: 100 },
|
||||
});
|
||||
rootObject.addChild(avatarArrowEntity);
|
||||
|
||||
this.isVisible = function() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
function mousePressEvent(event) {
|
||||
// Entities.setZonesArePickable(false);
|
||||
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
for (var i = 0; i < waypointEntities.length; ++i) {
|
||||
var entity = waypointEntities[i];
|
||||
print("Checkit for hit", entity.__extra__.waypoint.name);
|
||||
var result = raySphereIntersection(pickRay.origin, pickRay.direction, entity.worldPosition, 0.1);//entity.worldScale);
|
||||
if (result) {
|
||||
print("Pressed entity: ", entity.id);
|
||||
print("Pressed waypoint: ", entity.__extra__.waypoint.name);
|
||||
print("Teleporting...");
|
||||
MyAvatar.position = entity.__extra__.waypoint.position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// var result = Entities.findRayIntersection(pickRay, false);
|
||||
// if (result.intersects) {
|
||||
// var entity = entityManager.get(result.entityID);
|
||||
// if (entity) {
|
||||
// print("Pressed entity: ", entity.id);
|
||||
// }
|
||||
// if (entity && entity.__extra__.waypoint) {
|
||||
// print("Pressed waypoint: ", entity.__extra__.waypoint.name);
|
||||
// print("Teleporting...");
|
||||
// MyAvatar.position = entity.__extra__.waypoint.position;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Entities.setZonesArePickable(true);
|
||||
};
|
||||
|
||||
var time = 0;
|
||||
Script.update.connect(function(dt) {
|
||||
time += dt;
|
||||
// Update tracked entities
|
||||
for (var i = 0; i < trackedEntities.length; ++i) {
|
||||
entity = trackedEntities[i];
|
||||
var entityID = entity.__extra__.trackingEntityID;
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
properties.position = Vec3.subtract(properties.position, center);
|
||||
properties.position = Vec3.multiply(properties.position, ROOT_SCALE);
|
||||
entity.position = properties.position;
|
||||
}
|
||||
|
||||
|
||||
var position = Vec3.subtract(MyAvatar.position, center)
|
||||
position.y += 60 + (Math.sin(time) * 10);
|
||||
position = Vec3.multiply(position, ROOT_SCALE);
|
||||
avatarArrowEntity.position = position;
|
||||
// Vec3.print("Position:", avatarArrowEntity.position);
|
||||
|
||||
// rootObject.position = Vec3.sum(position, { x: 0, y: Math.sin(time) / 30, z: 0 });
|
||||
//var ROOT_OFFSET = Vec3.multiply(0.3, Quat.getFront(MyAvatar.orientation));
|
||||
//var ROOT_POSITION = Vec3.sum(MyAvatar.position, ROOT_OFFSET);
|
||||
// position = ROOT_POSITION;
|
||||
rootObject.position = ROOT_POSITION;
|
||||
entityManager.update();
|
||||
|
||||
// Update waypoint highlights
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
for (var i = 0; i < waypointEntities.length; ++i) {
|
||||
var entity = waypointEntities[i];
|
||||
print("Checkit for hit", entity.__extra__.waypoint.name);
|
||||
var result = raySphereIntersection(pickRay.origin, pickRay.direction, entity.worldPosition, 0.1);//entity.worldScale);
|
||||
if (result) {
|
||||
print("Pressed entity: ", entity.id);
|
||||
print("Pressed waypoint: ", entity.__extra__.waypoint.name);
|
||||
print("Teleporting...");
|
||||
MyAvatar.position = entity.__extra__.waypoint.position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function setVisible(newValue) {
|
||||
if (visible != newValue) {
|
||||
visible = newValue;
|
||||
|
||||
if (visible) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.show = function() {
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
this.hide = function() {
|
||||
setVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
var map = null;
|
||||
map = Map(mapData);
|
||||
|
||||
// On press key
|
||||
Controller.keyPressEvent.connect(function(event) {
|
||||
if (event.text == "m") {
|
||||
if (!map) {
|
||||
map = Map(mapData);
|
||||
}
|
||||
|
||||
map.show();
|
||||
print("MAP!");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var mapData = {
|
||||
config: {
|
||||
// World dimensions that the minimap maps to
|
||||
worldDimensions: {
|
||||
x: 10.0,
|
||||
y: 10.0,
|
||||
z: 10.0,
|
||||
},
|
||||
// The center of the map should map to this location in the center of the area
|
||||
worldCenter: {
|
||||
x: 5.0,
|
||||
y: 5.0,
|
||||
z: 5.0,
|
||||
},
|
||||
// Map dimensions
|
||||
mapDimensions: {
|
||||
x: 10.0,
|
||||
y: 10.0,
|
||||
z: 10.0,
|
||||
},
|
||||
|
||||
// Can this be automated? Tag entities that should be included? Store in UserData?
|
||||
objects: [
|
||||
{
|
||||
type: "Model",
|
||||
modelURL: "https://hifi-public.s3.amazonaws.com/ozan/sets/huffman_set/huffman_set.fbx",
|
||||
},
|
||||
],
|
||||
},
|
||||
waypoints: [
|
||||
{
|
||||
name: "Forest's Edge",
|
||||
position: {
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
// entityManager = new OverlayManager();
|
||||
// entityManager = new EntityManager();
|
||||
//
|
||||
// var rootEntity = entityManager.addBare();
|
||||
//
|
||||
// var time = 0;
|
||||
//
|
||||
//
|
||||
// rootEntity.scale = 0.1;
|
||||
// Script.include("sfData.js");
|
||||
// rootEntity.addChild(entity);
|
||||
entityManager.update();
|
|
@ -266,4 +266,4 @@
|
|||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new Flashlight();
|
||||
});
|
||||
});
|
|
@ -115,6 +115,21 @@ void ObjectMotionState::setMotionType(MotionType motionType) {
|
|||
_motionType = motionType;
|
||||
}
|
||||
|
||||
void ObjectMotionState::updateCCDConfiguration() {
|
||||
if (_body) {
|
||||
if (_shape) {
|
||||
btVector3 center;
|
||||
btScalar radius;
|
||||
_shape->getBoundingSphere(center, radius);
|
||||
_body->setCcdMotionThreshold(radius * 2.0f);
|
||||
_body->setCcdSweptSphereRadius(radius);
|
||||
} else {
|
||||
// Disable CCD
|
||||
_body->setCcdMotionThreshold(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMotionState::setRigidBody(btRigidBody* body) {
|
||||
// give the body a (void*) back-pointer to this ObjectMotionState
|
||||
if (_body != body) {
|
||||
|
@ -125,6 +140,7 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) {
|
|||
if (_body) {
|
||||
_body->setUserPointer(this);
|
||||
}
|
||||
updateCCDConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +203,8 @@ bool ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
if (_shape != newShape) {
|
||||
_shape = newShape;
|
||||
_body->setCollisionShape(_shape);
|
||||
|
||||
updateCCDConfiguration();
|
||||
} else {
|
||||
// huh... the shape didn't actually change, so we clear the DIRTY_SHAPE flag
|
||||
flags &= ~Simulation::DIRTY_SHAPE;
|
||||
|
|
|
@ -137,6 +137,7 @@ protected:
|
|||
virtual bool isReadyToComputeShape() = 0;
|
||||
virtual btCollisionShape* computeNewShape() = 0;
|
||||
void setMotionType(MotionType motionType);
|
||||
void updateCCDConfiguration();
|
||||
|
||||
// clearObjectBackPointer() overrrides should call the base method, then actually clear the object back pointer.
|
||||
virtual void clearObjectBackPointer() { _type = MOTIONSTATE_TYPE_INVALID; }
|
||||
|
|
Loading…
Reference in a new issue