overte/examples/voxels.js

295 lines
8.5 KiB
JavaScript

var controlHeld = false;
var shiftHeld = false;
Script.include([
"libraries/toolBars.js",
]);
var isActive = false;
var toolIconUrl = "http://headache.hungry.com/~seth/hifi/";
var toolHeight = 50;
var toolWidth = 50;
var addingVoxels = false;
var deletingVoxels = false;
offAlpha = 0.5;
onAlpha = 0.9;
function floorVector(v) {
return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)};
}
function vectorToString(v){
return "{" + v.x + ", " + v.x + ", " + v.x + "}";
}
var toolBar = (function () {
var that = {},
toolBar,
activeButton,
addVoxelButton,
deleteVoxelButton,
addTerrainButton;
function initialize() {
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.voxel.toolbar", function (windowDimensions, toolbar) {
return {
x: windowDimensions.x - 8*2 - toolbar.width * 2,
y: (windowDimensions.y - toolbar.height) / 2
};
});
activeButton = toolBar.addTool({
imageURL: "http://s3.amazonaws.com/hifi-public/images/tools/polyvox.svg",
width: toolWidth,
height: toolHeight,
alpha: onAlpha,
visible: true,
});
addVoxelButton = toolBar.addTool({
imageURL: toolIconUrl + "voxel-add.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
width: toolWidth,
height: toolHeight,
alpha: offAlpha,
visible: false
});
deleteVoxelButton = toolBar.addTool({
imageURL: toolIconUrl + "voxel-delete.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
width: toolWidth,
height: toolHeight,
alpha: offAlpha,
visible: false
});
addTerrainButton = toolBar.addTool({
imageURL: toolIconUrl + "voxel-terrain.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
width: toolWidth,
height: toolHeight,
alpha: onAlpha,
visible: false
});
that.setActive(false);
}
that.setActive = function(active) {
if (active != isActive) {
isActive = active;
that.showTools(isActive);
}
toolBar.selectTool(activeButton, isActive);
};
// Sets visibility of tool buttons, excluding the power button
that.showTools = function(doShow) {
toolBar.showTool(addVoxelButton, doShow);
toolBar.showTool(deleteVoxelButton, doShow);
toolBar.showTool(addTerrainButton, doShow);
};
that.mousePressEvent = function (event) {
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
if (activeButton === toolBar.clicked(clickedOverlay)) {
that.setActive(!isActive);
return true;
}
if (addVoxelButton === toolBar.clicked(clickedOverlay)) {
if (addingVoxels) {
addingVoxels = false;
deletingVoxels = false;
toolBar.setAlpha(offAlpha, addVoxelButton);
toolBar.setAlpha(offAlpha, deleteVoxelButton);
toolBar.selectTool(addVoxelButton, false);
toolBar.selectTool(deleteVoxelButton, false);
} else {
addingVoxels = true;
deletingVoxels = false;
toolBar.setAlpha(onAlpha, addVoxelButton);
toolBar.setAlpha(offAlpha, deleteVoxelButton);
}
return true;
}
if (deleteVoxelButton === toolBar.clicked(clickedOverlay)) {
if (deletingVoxels) {
deletingVoxels = false;
addingVoxels = false;
toolBar.setAlpha(offAlpha, addVoxelButton);
toolBar.setAlpha(offAlpha, deleteVoxelButton);
} else {
deletingVoxels = true;
addingVoxels = false;
toolBar.setAlpha(offAlpha, addVoxelButton);
toolBar.setAlpha(onAlpha, deleteVoxelButton);
}
return true;
}
if (addTerrainButton === toolBar.clicked(clickedOverlay)) {
addTerrainBlock();
return true;
}
}
Window.domainChanged.connect(function() {
that.setActive(false);
});
that.cleanup = function () {
toolBar.cleanup();
// Overlays.deleteOverlay(activeButton);
};
initialize();
return that;
}());
function addTerrainBlock() {
var myPosDiv16 = Vec3.multiply(Vec3.sum(MyAvatar.position, {x:8, x:8, z:8}), 1.0 / 16.0);
var myPosDiv16Floored = floorVector(myPosDiv16);
var baseLocation = Vec3.multiply(myPosDiv16Floored, 16.0);
if (baseLocation.y + 8 > MyAvatar.position.y) {
baseLocation.y -= 16;
}
print("myPosDiv16 is " + vectorToString(myPosDiv16));
print("MyPosDiv16Floored is " + vectorToString(myPosDiv16Floored));
print("baseLocation is " + vectorToString(baseLocation));
alreadyThere = Entities.findEntities(baseLocation, 1.0);
for (var i = 0; i < alreadyThere.length; i++) {
var id = alreadyThere[i];
var properties = Entities.getEntityProperties(id);
if (properties.name == "terrain") {
print("already terrain there");
return;
}
}
var polyVoxId = Entities.addEntity({
type: "PolyVox",
name: "terrain",
position: baseLocation,
dimensions: { x: 16, y: 16, z: 16 },
voxelVolumeSize: {x:16, y:16, z:16},
voxelSurfaceStyle: 2
});
Entities.setAllVoxels(polyVoxId, 255);
for (var y = 8; y < 16; y++) {
for (var x = 0; x < 16; x++) {
for (var z = 0; z < 16; z++) {
Entities.setVoxel(polyVoxId, {x: x, y: y, z: z}, 0);
}
}
}
return true;
}
function attemptVoxelChange(pickRayDir, intersection) {
var properties = Entities.getEntityProperties(intersection.entityID);
if (properties.type != "PolyVox") {
return false;
}
if (addingVoxels == false && deletingVoxels == false) {
return false;
}
var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection);
var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir);
pickRayDirInVoxelSpace = Vec3.normalize(pickRayDirInVoxelSpace);
var doAdd = addingVoxels;
var doDelete = deletingVoxels;
if (controlHeld) {
doAdd = deletingVoxels;
doDelete = addingVoxels;
}
if (doDelete) {
var toErasePosition = Vec3.sum(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1));
return Entities.setVoxel(intersection.entityID, floorVector(toErasePosition), 0);
}
if (doAdd) {
var toDrawPosition = Vec3.subtract(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1));
return Entities.setVoxel(intersection.entityID, floorVector(toDrawPosition), 255);
}
}
function mousePressEvent(event) {
if (!event.isLeftButton) {
return;
}
if (toolBar.mousePressEvent(event)) {
return;
}
var pickRay = Camera.computePickRay(event.x, event.y);
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
if (intersection.intersects) {
if (attemptVoxelChange(pickRay.direction, intersection)) {
return;
}
}
// if the PolyVox entity is empty, we can't pick against its "on" voxels. try picking against its
// bounding box, instead.
intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking
if (intersection.intersects) {
attemptVoxelChange(pickRay.direction, intersection);
}
}
function keyPressEvent(event) {
if (event.text == "CONTROL") {
controlHeld = true;
}
if (event.text == "SHIFT") {
shiftHeld = true;
}
}
function keyReleaseEvent(event) {
if (event.text == "CONTROL") {
controlHeld = false;
}
if (event.text == "SHIFT") {
shiftHeld = false;
}
}
function cleanup() {
for (var i = 0; i < overlays.length; i++) {
Overlays.deleteOverlay(overlays[i]);
}
toolBar.cleanup();
}
Controller.mousePressEvent.connect(mousePressEvent);
Controller.keyPressEvent.connect(keyPressEvent);
Controller.keyReleaseEvent.connect(keyReleaseEvent);
Script.scriptEnding.connect(cleanup);