Interfacing the law javascript Zalan Szakacs: Difference between revisions

From XPUB & Lens-Based wiki
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 283: Line 283:




'''ThreeJs'''
=='''ThreeJs'''==




Line 547: Line 547:
</html>
</html>


</pre>
'''Shapes generated based on ASCII numeric values'''
[https://jsfiddle.net/n3gjcvdp/ JS Fiddle to the script]
<gallery class="center" widths=692px heights=405px>
Steps catalogue.gif
</gallery>
<br>
''HTML''
<pre>
<!DOCTYPE html>
<html>
<head>
<title>XPPL VOLUMETRIC CATALOGUE </title>
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body{
cccccc;
font-family: 'Karla', sans-serif;
font-size:15px;
text-align:left;
background-color: #140b33;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 10%;
padding: 10px;
}
a {
color: #444b7c;
}
</style>
</head>
<body>
<canvas id="viewer"></canvas>
<div id="info"><a  target="_blank" rel="noopener">XPPL VOLUMETRIC CATALOGUE  <br> <br> Feel free to move around and explore the content of the library by clicking on the volumetric shapes</div>
<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>
<script src="Raycaster.js"></script>
<script src="setup8.js"></script>
</body>
</html>
</pre>
''JS''
<pre>
const MAX_DISTANCE = 12000;
const MAX_SPHERE_RADIUS = 700;
let camera, scene, controls, renderer, material;
console.clear();
let bookTitles = [{
    title: "Mac OS X Leopard Edition",
    id: "1",
    type: 'sphere'
  },
  {
    title: "The Qmail Handbook",
    id: "2",
    type: 'sphere'
  },
  {
    title: "Hardening Network Infrastructure: Bulletproof Your Systems Before You Are Hacked!",
    id: "3",
    type: 'sphere'
  },
  {
    title: "Cocoa Programming for Mac OS X Second Edition",
    id: "4",
    type: 'sphere'
  },
  {
    title: "LDAP System Administration",
    id: "5",
    type: 'sphere'
  },
  {
    title: "Learning Unix for Mac OS X",
    id: "6",
    type: 'sphere'
  },
  {
    title: "Mac OS X Panther for Unix Geeks",
    id: "7",
    type: 'sphere'
  },
  {
    title: "Linux System Administration",
    id: "8",
    type: 'sphere2'
  },
  {
    title: "Managing and Using MYSQL",
    id: "9",
    type: 'sphere'
  },
  {
    title: "MYSQL In a Nutshell",
    id: "10",
    type: 'sphere2'
  },
  {
    title: "Actionscript for Flash MX: The Definitive Guide",
    id: "11",
    type: 'sphere2'
  },
  {
    title: "Programming Firefox",
    id: "12",
    type: 'sphere'
  },
  {
    title: "Learning PHP and MYSQL",
    id: "13",
    type: 'sphere'
  },
  {
    title: "Learning the Bash Shell",
    id: "14",
    type: 'sphere2'
  },
  {
    title: "GNU Emacs Pocket Reference",
    id: "15",
    type: 'sphere'
  },
  {
    title: "SQL Pocket Guide",
    id: "16",
    type: 'sphere2'
  },
  {
    title: "HTML Pocket Reference",
    id: "17",
    type: 'sphere2'
  },
  {
    title: "Regular Expression Pocket Reference",
    id: "18",
    type: 'sphere2'
  },
  {
    title: "Apache 2 Pocket Reference",
    id: "19",
    type: 'sphere'
  },
  {
    title: "CSS Pocket Reference",
    id: "20",
    type: 'sphere2'
  },
  {
    title: "vi Editor Pocket Reference",
    id: "21",
    type: 'sphere2'
  },
  {
    title: "The Book of Inkscape",
    id: "22",
    type: 'sphere'
  },
  {
    title: "Working with Mediawiki",
    id: "23",
    type: 'sphere2'
  },
  {
    title: "Beginning Game Development with Python and Pygame",
    id: "24",
    type: 'sphere'
  },
  {
    title: "Game Programming with Python, Lua, and Ruby 1 edition",
    id: "25",
    type: 'sphere2'
  },
  {
    title: "Data Modeling for Everyone",
    id: "26",
    type: 'sphere'
  },
  {
    title: "The Ultimate Guide to the Vi and Ex Text Editors",
    id: "27",
    type: 'sphere2'
  },
  {
    title: "Getting Gread Sounds: The Microphone Book",
    id: "28",
    type: 'sphere2'
  },
  {
    title: "How to Think Like a Computer Scientist",
    id: "29",
    type: 'sphere2'
  },
  {
    title: "Python Pocket Reference",
    id: "30",
    type: 'sphere2'
  },
  {
    title: "Things That Talk",
    id: "31",
    type: 'sphere2'
  },
  {
    title: "The Social Construction of What?",
    id: "32",
    type: 'sphere2'
  },
  {
    title: "Instruments and the Imagination",
    id: "33",
    type: 'sphere'
  },
  {
    title: "Mind, Machines and Human Consciousness",
    id: "34",
    type: 'sphere2'
  },
  {
    title: "The Psychopath Test",
    id: "35",
    type: 'sphere2'
  },
  {
    title: "The Selfish Gene",
    id: "36",
    type: 'sphere2'
  },
  {
    title: "Pandora's Hope",
    id: "37",
    type: 'sphere2'
  },
  {
    title: "The New Spirit of Capitalism",
    id: "38",
    type: 'sphere'
  },
  {
    title: "Distinction: A Social Critique of the Judgement of Taste",
    id: "39",
    type: 'sphere'
  },
  {
    title: "The Political Economy of Media: Enduring Issues, Emerging Dilemmas",
    id: "40",
    type: 'sphere'
  },
  {
    title: "The Dustbin of History",
    id: "41",
    type: 'sphere'
  },
  {
    title: "Inventing The Victorians",
    id: "42",
    type: 'sphere1'
  },
  {
    title: "Age of the Extremes: The Short Twentieth Century 1914-1991",
    id: "43",
    type: 'sphere1'
  },
  {
    title: "Lipstick Traces",
    id: "44",
    type: 'sphere1'
  },
  {
    title: "False Dawn: The Delusions of Global Capitalism",
    id: "45",
    type: 'sphere1'
  },
  {
    title: "Debt: The First 5000 Years",
    id: "46",
    type: 'sphere1'
  },
  {
    title: "Georges Bataille: An Intellectual Biography",
    id: "47",
    type: 'sphere1'
  },
  {
    title: "The Enlightenment Reader",
    id: "48",
    type: 'sphere2'
  },
  {
    title: "The Century",
    id: "49",
    type: 'sphere2'
  },
  {
    title: "Rethinking Media Pluralism",
    id: "50",
    type: 'sphere2'
  },
  {
    title: "The Philosophy of Symbolic Forms",
    id: "51",
    type: 'sphere'
  },
  {
    title: "Archaeology",
    id: "52",
    type: 'sphere1'
  },
  {
    title: "The Chomsky Reader",
    id: "53",
    type: 'sphere1'
  },
  {
    title: "The Society of Mind",
    id: "54",
    type: 'sphere1'
  },
  {
    title: "Interference: A Grand Scientific Musical Theory",
    id: "55",
    type: 'sphere1'
  },
  {
    title: "Understanding media economics",
    id: "56",
    type: 'sphere1'
  },
  {
    title: "Convergence culture",
    id: "57",
    type: 'sphere1'
  },
  {
    title: "Digital Labor",
    id: "58",
    type: 'sphere1'
  },
  {
    title: "The culture of connectivity",
    id: "59",
    type: 'sphere1'
  },
  {
    title: "Anti-Media",
    id: "60",
    type: 'sphere1'
  },
  {
    title: "Holding On to Reality: The Nature of Information at the Turn of the Millennium",
    id: "61",
    type: 'sphere1'
  },
  {
    title: "Organized Networks",
    id: "62",
    type: 'sphere1'
  },
  {
    title: "Over Mediatheorie",
    id: "63",
    type: 'sphere'
  },
  {
    title: "Post Truth",
    id: "64",
    type: 'sphere'
  },
  {
    title: "Weapons of Math Destruction",
    id: "65",
    type: 'sphere'
  },
  {
    title: "Media Ecologies: Materialist Energies in Art and Technoculture",
    id: "66",
    type: 'sphere'
  },
  {
    title: "The Internet Is Not The Answer",
    id: "67",
    type: 'sphere2'
  },
  {
    title: "Wired for war - Robotics revolution and conflict in the 21st century",
    id: "68",
    type: 'sphere'
  },
  {
    title: "Interface Culture",
    id: "69",
    type: 'sphere2'
  },
  {
    title: "The Interface Effect",
    id: "70",
    type: 'sphere'
  },
  {
    title: "Present Shock: When Everything Happens Now",
    id: "71",
    type: 'sphere'
  },
  {
    title: "Bastard Culture!: How User Participation Transforms Cultural Production",
    id: "72",
    type: 'sphere2'
  },
  {
    title: "Media Virus! Hidden Agendas in Popular Culture",
    id: "73",
    type: 'sphere'
  },
  {
    title: "Loving Big Brother: Surveillance Culture and Performance Space",
    id: "74",
    type: 'sphere3'
  },
  {
    title: "Selections from Cultural Writings",
    id: "75",
    type: 'sphere2'
  },
  {
    title: "Dark Money: The Hidden History of the Billionairs behind the Rise of the Radical Right",
    id: "76",
    type: 'sphere3'
  },
  {
    title: "Walter Benjamin for beginners",
    id: "77",
    type: 'sphere3'
  },
  {
    title: "What is Situationism? A Reader",
    id: "78",
    type: 'sphere'
  },
  {
    title: "Cyburbia",
    id: "79",
    type: 'sphere'
  },
  {
    title: "Mondothèque a radiated book/un livre irradiant/een irradiërend boek",
    id: "80",
    type: 'sphere3'
  },
  {
    title: "Save and Forget",
    id: "81",
    type: 'sphere3'
  },
  {
    title: "The World Explained",
    id: "82",
    type: 'sphere3'
  },
  {
    title: "Information - Documents of Contemporary Art",
    id: "83",
    type: 'sphere3'
  },
  {
    title: "Postscript on the Societies of Control",
    id: "84",
    type: 'sphere3'
  },
  {
    title: "Ethics Subjectivity and Truth",
    id: "85",
    type: 'sphere2'
  },
  {
    title: "The Infinite Conversation",
    id: "86",
    type: 'sphere'
  },
  {
    title: "Identity and Difference",
    id: "87",
    type: 'sphere'
  },
  {
    title: "Jean Paul A Reader",
    id: "88",
    type: 'sphere'
  },
  {
    title: "The Ear of the Other",
    id: "89",
    type: 'sphere'
  },
  {
    title: "Statements on Appropriation (London Version)",
    id: "90",
    type: 'sphere2'
  },
  {
    title: "An Introduction to Western Philosophy",
    id: "91",
    type: 'sphere'
  },
  {
    title: "The Postmodern Turn",
    id: "92",
    type: 'sphere'
  },
  {
    title: "Ideology",
    id: "93",
    type: 'sphere'
  },
  {
    title: "Ludwig Wittgenstein",
    id: "94",
    type: 'sphere2'
  },
  {
    title: "The Human Condition",
    id: "95",
    type: 'sphere'
  },
  {
    title: "Introducing Foucault",
    id: "96",
    type: 'sphere'
  },
  {
    title: "The Lives of Michel Foucault",
    id: "97",
    type: 'sphere'
  },
  {
    title: "Discipline and Punish",
    id: "98",
    type: 'sphere'
  },
  {
    title: "Logic of Scientific Discovery",
    id: "99",
    type: 'sphere'
  },
  {
    title: "Intensive Science and Virtual Philosophy",
    id: "100",
    type: 'sphere2'
  },
  {
    title: "Kant and the Platypus: Essays on Language and Cognition",
    id: "101",
    type: 'sphere'
  },
  {
    title: "Turning Back the Clock",
    id: "102",
    type: 'sphere'
  },
  {
    title: "Travels in hyper reality : essays",
    id: "103",
    type: 'sphere'
  },
  {
    title: "On revolution",
    id: "104",
    type: 'sphere3'
  },
  {
    title: "Introducing Kant",
    id: "105",
    type: 'sphere3'
  },
  {
    title: "The Perfect Crime",
    id: "106",
    type: 'sphere3'
  },
  {
    title: "Introducing Baudrillard",
    id: "107",
    type: 'sphere1'
  },
  {
    title: "The structure of scientific revolutions",
    id: "108",
    type: 'sphere3'
  },
  {
    title: "The World Turned Upside Down: Radical Ideas During the English Revolution",
    id: "109",
    type: 'sphere1'
  },
  {
    title: "On Wine and Hishish",
    id: "110",
    type: 'sphere1'
  },
  {
    title: "Lacan For Beginners",
    id: "111",
    type: 'sphere3'
  },
  {
    title: "Late Marxism",
    id: "112",
    type: 'sphere1'
  },
  {
    title: "Adorno",
    id: "113",
    type: 'sphere1'
  },
  {
    title: "Dialectic of Enlightenment",
    id: "114",
    type: 'sphere3'
  },
  {
    title: "Walter Benjamin: A Biography",
    id: "115",
    type: 'sphere1'
  },
  {
    title: "A Thousand Years of Nonlinear History",
    id: "116",
    type: 'sphere3'
  },
  {
    title: "Barthes: Selected Writings",
    id: "117",
    type: 'sphere3'
  },
  {
    title: "Camera Lucida: Reflections on Photography",
    id: "118",
    type: 'sphere1'
  },
  {
    title: "Derrida For Beginners",
    id: "119",
    type: 'sphere1'
  },
  {
    title: "System and Writing in the Philosophy of Jacques Derrida",
    id: "120",
    type: 'sphere1'
  },
  {
    title: "Exploring Humans",
    id: "121",
    type: 'sphere2'
  },
  {
    title: "Urheberrecht im Alltag: Kopieren, bearbeiten, selber machen",
    id: "122",
    type: 'sphere3'
  },
  {
    title: "DATA browser 02: Engineering Culture",
    id: "123",
    type: 'sphere1'
  },
  {
    title: "DATA browser 01: Economising Culture",
    id: "124",
    type: 'sphere1'
  },
  {
    title: "The Mag.net reader 3, Processual Publishing. Actual Gesture",
    id: "125",
    type: 'sphere'
  },
  {
    title: "New Media Art",
    id: "126",
    type: 'sphere1'
  },
  {
    title: "Digital Prohibition",
    id: "127",
    type: 'sphere1'
  },
  {
    title: "The Cathedral & The Bazaar",
    id: "128",
    type: 'sphere3'
  },
  {
    title: "The Code Book",
    id: "129",
    type: 'sphere1'
  },
  {
    title: "DiY Survival // There is No Subculture Only Subversion",
    id: "130",
    type: 'sphere3'
  },
  {
    title: "Guide to Open Content Licenses",
    id: "131",
    type: 'sphere3'
  },
  {
    title: "DATA browser 3: Curating Immateriality",
    id: "132",
    type: 'sphere3'
  },
  {
    title: "Formen interaktiver Medienkunst",
    id: "133",
    type: 'sphere3'
  },
  {
    title: "Oulipo Compendium",
    id: "134",
    type: 'sphere3'
  },
  {
    title: "Convergence: The International Journal of Research into New Media Technologies - Volume 12 Number 3 August 2004",
    id: "135",
    type: 'sphere1'
  },
  {
    title: "Perl for Web Site Management",
    id: "136",
    type: 'sphere1'
  },
  {
    title: "Seven Hundred Penguins",
    id: "137",
    type: 'sphere3'
  },
  {
    title: "Mondotheque: a radiated book / un livre irradiant / een iradierend boek",
    id: "138",
    type: 'sphere1'
  },
  {
    title: "An Atlas of Typeforms",
    id: "139",
    type: 'sphere'
  },
  {
    title: "Structure of the Visual Book",
    id: "140",
    type: 'sphere3'
  },
  {
    title: "The Uses of Literacy",
    id: "141",
    type: 'sphere1'
  },
  {
    title: "Control and Freedom: Power and Paranoia in the Age of Fiber Optics",
    id: "142",
    type: 'sphere2'
  },
  {
    title: "The New Media Reader",
    id: "143",
    type: 'sphere1'
  },
  {
    title: "Art and Electronic Media",
    id: "144",
    type: 'sphere3'
  },
  {
    title: "The Situationist City",
    id: "145",
    type: 'sphere1'
  },
  {
    title: "The Absolute Report: Time Space Code Memory",
    id: "146",
    type: 'sphere3'
  },
  {
    title: "Ashes and Broken Brickwork of a Logical Theory",
    id: "147",
    type: 'sphere3'
  },
  {
    title: "Surrealist Painters and Poets: An Anthology",
    id: "148",
    type: 'sphere3'
  },
  {
    title: "Guy Debord and the Situationists International",
    id: "149",
    type: 'sphere1'
  },
  {
    title: "A Bed a Chair and a Table",
    id: "150",
    type: 'sphere3'
  },
  {
    title: "Software Studies a lexicon",
    id: "151",
    type: 'sphere3'
  },
  {
    title: "The Rise of the Network Society, With a New Preface: Volume I: The Information Age: Economy, Society, and Culture (Information Age Series)",
    id: "152",
    type: 'sphere3'
  },
  {
    title: "I Read Where I Am: Exploring New Information Cultures",
    id: "153",
    type: 'sphere3'
  },
  {
    title: "Present Continuous Past(s): Media Art. Strategies of Presentation, Mediation and Dissemination",
    id: "154",
    type: 'sphere1'
  },
  {
    title: "exquisite_code",
    id: "155",
    type: 'sphere1'
  },
  {
    title: "Uncreative Writing",
    id: "156",
    type: 'sphere3'
  },
  {
    title: "The Electronic Revolution",
    id: "157",
    type: 'sphere2'
  },
  {
    title: "The Invisible Generation",
    id: "158",
    type: 'sphere3'
  },
  {
    title: "Cybernetics & Ghosts",
    id: "159",
    type: 'sphere1'
  },
  {
    title: "Digital (Steve Trim 2 reading)",
    id: "160",
    type: 'sphere1'
  },
  {
    title: "A Preface to Plato",
    id: "161",
    type: 'sphere3'
  },
  {
    title: "Writing Machines",
    id: "162",
    type: 'sphere3'
  },
  {
    title: "Gramophone, Film, Typewriter",
    id: "163",
    type: 'sphere3'
  },
  {
    title: "Literature Media",
    id: "164",
    type: 'sphere1'
  },
  {
    title: "iSpace: Printed English after Joyce, Shannon, Derrida",
    id: "165",
    type: 'sphere1'
  },
  {
    title: "Orality and Literacy",
    id: "166",
    type: 'sphere2'
  },
  {
    title: "International Picture Language",
    id: "167",
    type: 'sphere1'
  },
  {
    title: "Protocol",
    id: "168",
    type: 'sphere1'
  },
  {
    title: "A Prehistory of the Cloud",
    id: "169",
    type: 'sphere1'
  },
  {
    title: "Paratexts: Thresholds of Interpretation",
    id: "170",
    type: 'sphere1'
  }
];
var raycaster = new THREE.Raycaster(),
  INTERSECTED;
var mouse = new THREE.Vector2();
//mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
//mouse.y = -(event.clientY/ window.innerHeight) * 2 + 1;
let objects = [];
function setupBooks() {
  bookTitles.forEach(book => {
    let geometry;
    let material;
    let radius = Math.floor(Math.random() * MAX_SPHERE_RADIUS);
    switch (book.type) {
      case 'sphere':
        geometry = new THREE.SphereGeometry(radius, 3, 30);
        break;
      case 'sphere1':
        geometry = new THREE.SphereGeometry(radius, 5, 3);
        break;
      case 'sphere2':
        geometry = new THREE.SphereGeometry(radius, 10, 10);
        break;
      case 'sphere3':
        geometry = new THREE.SphereGeometry(radius, 1, 1);
        break;
      case 'cone':
        geometry = new THREE.ConeGeometry(radius, radius, radius, radius, 50, 50);
        break;
      case 'cylinder':
        geometry = new Cylinder.BoxGeometry(radius, radius, radius, 10, 10);
        break;
      case 'cube':
        geometry = new THREE.BoxGeometry(radius, radius, radius, 10, 10);
        break;
    }
    material = new THREE.MeshPhongMaterial({
      color: Math.random() * 0xff00000 - 0xff00000
    });
    material.flatShading = true;
    // Add missing material
    let mesh = new THREE.Mesh(geometry, material);
    mesh.speed = Math.random() * 0.05;
    mesh.position.copy(getRandomVector(MAX_DISTANCE));
    objects.push(mesh);
    scene.add(mesh);
  });
}
function createSpace() {
  let dots = new THREE.Object3D();
  for (var i = 0; i < 10000; i++) {
    var circleGeometry = new THREE.SphereGeometry(50, Math.random() * 5, Math.random() * 5);
    var material = new THREE.MeshBasicMaterial({
      color: Math.random() * 0xff00000 - 0xff00000,
      side: THREE.DoubleSide
    });
    material.flatShading = true;
    var circle = new THREE.Mesh(circleGeometry, material);
    let direction = getRandomVector().normalize();
    let minDistance = MAX_DISTANCE * 5;
    let maxDistance = minDistance + 0.5;
    direction.multiplyScalar(Math.random() * (maxDistance - minDistance) + minDistance);
    circle.position.add(direction);
    dots.add(circle);
  }
  scene.add(dots);
}
function onMouseMove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  mouseX = event.clientX - window.innerWidth / 2;
  mouseY = event.clientY - window.innerHeight / 2;
  camera.position.x += (mouseX - camera.position.x) * 0.01;
  camera.position.y += (mouseY - camera.position.y) * 0.01;
  camera.lookAt(scene.position);
}
function getRandomVector(max_distance) {
  if (max_distance === undefined)
    max_distance = 1;
  return new THREE.Vector3(getRandom(max_distance), getRandom(max_distance), getRandom(max_distance));
}
function getRandom(max_distance) {
  let random = Math.random() * max_distance;
  random *= Math.floor(Math.random() * 2) == 1 ? 1 : -1;
  return random;
}
function animate() {
  requestAnimationFrame(animate);
  if (controls.enableDamping) {
    controls.update();
  }
  objects.forEach(object => {
    object.rotation.y += object.speed;
  });
  render();
}
function render() {
  renderer.render(scene, camera);
}
function init() {
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x140b33);
  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 300000);
  camera.position.set(MAX_DISTANCE, MAX_DISTANCE, MAX_DISTANCE);
  camera.updateProjectionMatrix();
  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.maxDistance = MAX_DISTANCE * 3;
  controls.target = new THREE.Vector3(0, 0, 0);
  controls.rotateSpeed = .2;
  controls.enableDamping = true;
  console.log(controls.enableDamping);
  controls.dampingFactor = .15;
  controls.panSpeed = .15;
  controls.screenSpacePanning = true;
  scene.add(camera);
  scene.add(new THREE.DirectionalLight(0xffffff));
  scene.add(new THREE.DirectionalLight(0x002288));
  scene.add(new THREE.AmbientLight(0x222222));
  renderer.setPixelRatio(window.devicePixelRatio);
  let viewer = document.querySelector('#viewer');
  viewer.parentNode.replaceChild(renderer.domElement, viewer);
}
init();
animate();
createSpace();
setupBooks();
window.onresize = function() {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
};
</pre>
'''Final working script'''
''The string values of the titles and the metadata from the JSON file is generating the radius and the position of the shapes''
<gallery class="center" widths=692px heights=405px>
Screen Shot 2018-06-13 at 19.35.47.png
</gallery>
<br>
<pre>
<!DOCTYPE html>
<html>
<head>
    <title>XPPL VOLUMETRIC CATALOGUE </title>
    <meta charset="utf-8">
    <link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body{
           
                font-family: 'Karla', sans-serif;
                font-size:15px;
                text-align:left;
                background: #140b33;
                margin: 0px;
                overflow: hidden;
            }
            #info {
                position: absolute;
                top: 0px; width: 10%;
                padding: 10px;
            }
            a {
                color: #444b7c;
            }
            .swal-button {
                padding: 7px 19px;
                background-color: #aca4c1;
                font-size: 12px;
}
            .swal-title {
                margin: 0px;
                font-size: 16px;
                box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.21);
                margin-bottom: 28px;
}
            .swal-overlay {
                background-color: rgba(20, 13, 50, 0.6);
}
            .swal-modal {
                background-color: rgba(172, 164, 193, 1);
}
    </style>
</head>
<body>
    <div id="info"><a  target="_blank" rel="noopener"> <b> <font size="5"> XPPL VOLUMETRIC CATALOGUE </font> </b> <br>  <br> Feel free to move around and explore the content of the library by clicking on the volumetric shapes</div>
    <div id="container"></div>
    <canvas id="viewer"></canvas>
    <script src="https://rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script>
    <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script>
var category2color = new Object();
category2color["Technical"] = "#003d5d";
category2color["Science/History"] = "#f23d5d";
category2color["Media studies"] = "#8c3d5d";
category2color["Philosophy"] = "#723d5d";
category2color["Computer culture"] = "#423d5d";
category2color["Design / writing / publishing"] = "#ff0000";
category2color["Desk"] = "#09edff";
category2color["Art"] = "#ffedff";
category2color["Digital (Steve Trim 2 reading)"] = "#ffe1cc";
category2color["Media Studies (Femke Trim 3)"] = "#00e1cc";
category2color["Literature, Culture, Theory"] = "#00a1d4";
category2color["default"] = "#cdc1ec";
        console.clear();
const MAX_DISTANCE = 1000;
//
const MIN_DISTANCE = 200;
const MAX_SPHERE_RADIUS = 700;
var bookTitles;
var request = new XMLHttpRequest();
request.open('GET', 'export.json', true);
request.onload = function() {
  if (request.status >= 200 && request.status < 400) {
    var data = JSON.parse(request.responseText);
    //bookTitles = data;
    bookTitles = data.books[0];
    bookTitles.forEach(function(book) {
      book.type = "sphere";
      console.log('BOOK:', book);
    });
    console.log("got books", bookTitles)
    // loaded data, start
    init();
    animate();
  } else {
    // We reached our target server, but it returned an error
  }
};
request.onerror = function() {
  // There was a connection error of some sort
};
request.send();
// --- threeJS --- //
var renderer, scene, camera, distance, raycaster, projector;
var container = document.getElementById('container');
var raycaster = new THREE.Raycaster(),INTERSECTED;
var mouse = new THREE.Vector2();
var distance = 600;
// -- basic initialization -- //
function init() {
    renderer = new THREE.WebGLRenderer({
        antialias: true
    });
    renderer.setClearColor(0x140b33, 1);
    //renderer.setClearColor(0xFF00FF, 1.0);
    renderer.setSize(window.innerWidth, window.innerHeight);
    container.appendChild(renderer.domElement);
    renderer.clear();
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 300000);
  //  controls = new THREE.OrbitControls(camera);
    //camera.position.set(1, 1, -5);
    camera.position.set(MAX_DISTANCE/2, MAX_DISTANCE/20, MAX_DISTANCE/20);
    camera.updateProjectionMatrix();
    controls = new THREE.OrbitControls(camera, renderer.domElement);
  //  controls.maxDistance = MAX_DISTANCE * 3;
    controls.target = new THREE.Vector3(0, 0, 0);
    controls.rotateSpeed = .2;
    controls.enableDamping = true;
    console.log(controls.enableDamping);
    controls.dampingFactor = .15;
    controls.panSpeed = .15;
    controls.screenSpacePanning = true;
    // to disable zoom
    controls.enableZoom = true;
    // to disable rotation
    controls.enableRotate = true;
    // to disable pan
    controls.enablePan = true;
    scene.add(camera);
    //camera.position.set(-150, 10, 1);
    //controls.update();
  // scene.add(camera);
    light = new THREE.PointLight(0x404040);
    light.position.set(50, 0, 0);
    scene.add(light);
  /* light_two = new THREE.PointLight(0xffffff, 1, 4000);
    light_two.position.set(-100, 800, 800);
    lightAmbient = new THREE.AmbientLight(0x404040);
    scene.add(light, light_two, lightAmbient);*/
    // createSpheres();
    scene.add(new THREE.DirectionalLight(0xffffff));
    scene.add(new THREE.AmbientLight(0x222222));
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.clear();
    let viewer = document.querySelector('#viewer');
    viewer.parentNode.replaceChild(renderer.domElement, viewer);
   
window.onload = function () {
    createDiamond();
    createSpace();
   
    document.addEventListener('mousemove', onMouseMove, false);
    document.addEventListener('mousedown', onDocumentMouseDown, false);
    window.addEventListener('resize', onWindowResize, false);
};
}
// -- diamonds -- //
function catInobject(obj, category){ //checks if category is in object, if so return corresponding color
    if (obj.hasOwnProperty(category)) {
    var color = obj[category];
    } else { var color = obj["default"];
}
    return color;
}
function createDiamond() {
    diamondsGroup = new THREE.Object3D();
        console.log();
        bookTitles.forEach(function (book) {
            var chosencolor = catInobject(category2color, book.category);
            var sphere = new THREE.SphereGeometry(1.3, Math.random() * 50, Math.random() * 50);
            var material = new THREE.MeshPhongMaterial({
                color: chosencolor,//Math.random() * 0xff00000 - 0xff00000,
                shading: THREE.FlatShading
            });
            var sphere = new THREE.Mesh(sphere, material);
            sphere.position.x = get_x(book.title) * Math.random() * 100 - 1000;
            sphere.position.z = get_z(book.category) * Math.random() *  100 - 1000;
            sphere.rotation.y =get_y(book.fileformat) * Math.random() * 100 - 1000;
            //sphere.scale.x = sphere.scale.y = sphere.scale.z = Math.random() * 50 + 10;
            sphere.scale.x = sphere.scale.y = sphere.scale.z = get_size(book.title);
            sphere.userData = book;
            diamondsGroup.add(sphere);
        })
        diamondsGroup.position.x = 500;
        scene.add(diamondsGroup);
};
function get_size(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}
function get_x(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}
function get_y(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}
function get_z(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}
// -- dots on the back -- //
function createSpace() {
    let dots = new THREE.Object3D();
    for (let i = 0; i < 1000; i++) {
        let circleGeometry = new THREE.SphereGeometry(2, Math.random() * 5, Math.random() * 5);
        let color;
        if (Math.round(Math.random()) === 0)
            color = new THREE.Color('#003d5d');
        else
            //color = new THREE.Color('#f23d5d');
            color = new THREE.Color('#f23d5d');
        let material = new THREE.MeshPhongMaterial({
            color: color
            //side: THREE.DoubleSide
        });
        material.flatShading = true;
        //var material = new THREE.MeshBasicMaterial({
            //color : new THREE.Color(Math.floor(Math.random() * 1) === 1),
            //color : new THREE.Color(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0),
            //shading: THREE.FlatShading,
        //})
       
      var circle = new THREE.Mesh(circleGeometry, material);
        material.side = THREE.DoubleSide;
        circle.position.x = Math.random() * -distance * 100;
        circle.position.y = Math.random() * -distance * 8;
        circle.position.z = Math.random() * distance * 5;
        circle.rotation.y = Math.random() * 2 * Math.PI;
        circle.scale.x = circle.scale.y = circle.scale.z = Math.random() * 8 + 5;
        dots.add(circle);
    }
    dots.position.x = 14000;
    dots.position.y = 1500;
    dots.position.z = 4000;
    dots.rotation.y = Math.PI * 600;
    dots.rotation.z = Math.PI * 500;
    scene.add(dots);
};
/*
  let circle = new THREE.Mesh(circleGeometry, material);
    let direction = getRandomVector().normalize();
    let minDistance = MAX_DISTANCE * 8;
    let maxDistance = minDistance + 0.5;
    direction.multiplyScalar(Math.random() * (maxDistance - minDistance) + minDistance);
    circle.position.add(direction);
    dots.add(circle);
    }
    scene.add(dots);
}
*/
function getRandomVector(max_distance) {
    if (max_distance === undefined)
        max_distance = 1;
    return new THREE.Vector3(getRandom(max_distance), getRandom(max_distance), getRandom(max_distance));
}
function getRandom(max_distance) {
    let random = Math.random() * max_distance;
    random *= Math.floor(Math.random() * 2) === 1 ? 1 : -1;
    return random;
}
// -- events -- //
function onMouseMove(event) {
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    mouseX = event.clientX - window.innerWidth / 2 ;
    mouseY = event.clientY - window.innerHeight / 2 ;
    //camera.position.x += (mouseX - camera.position.x) * 0.01;
    //camera.position.y += (mouseY - camera.position.y) * 0.01;
    // camera.lookAt(scene.position);
};
function onDocumentMouseDown(event) {
    event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, camera);
    var intersects = raycaster.intersectObjects(diamondsGroup.children);
    if (intersects.length > 0) {
        var book = intersects[0].object.userData;
        console.log("click", book);
        //alert("book" + book.title);
        //swal(book.title + book.authors);
        swal(book.title + " \n " + " " + book.authors.map(function(x){return x.author_name}).join(", ") +  " \n" + book.category, {
            buttons: ["return", "open" ],
        }).then (function(button){
            console.log("button", button)
            if (button) {
              window.location = "/books/"+book.id
            }
           
        });
    }
};
function onDocumentMouseWheel( event ) {
    fov -= event.wheelDeltaY * 0.05;
    camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 );
}
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.updateProjectionMatrix();
    controls.update();
};
// ---- //
function animate() {
    requestAnimationFrame(animate);
    controls.update();
    render();
};
// -- render all -- //
function render() {
    var timer = 0.00001 * Date.now();
    for (var i = 0, l = diamondsGroup.children.length; i < l; i++) {
        var object = diamondsGroup.children[i];
        object.position.y = 500 * Math.cos(timer + i);
        object.rotation.y += Math.PI / 500;
    }
    // update the picking ray with the camera and mouse position
    raycaster.setFromCamera(mouse, camera);
    // calculate objects intersecting the picking ray
    var intersects = raycaster.intersectObjects(diamondsGroup.children);
    if (intersects.length > 0) {
        if (INTERSECTED != intersects[0].object) {
            if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
            INTERSECTED = intersects[0].object;
            INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
            INTERSECTED.material.emissive.setHex(Math.random() * 0xff00000 - 0xff00000);
        }
    } else {
        if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
        INTERSECTED = null;
    }
    renderer.render(scene, camera);
};
// -- run functions -- //
//init();
//animate();
    </script>
</body>
</html>
</pre>
</pre>

Latest revision as of 19:32, 13 June 2018



JavaScript


Canvas

First I started with basic beginners JavaScript tutorials and tried to explore the canvas library.




var canvas = document.querySelector('canvas')
	;

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;


var c  = canvas.getContext('2d');

// c.fillStyle = 'rgba(255, 0, 0, 1)';
// c.fillRect(100, 100, 100, 100);
// c.fillStyle = 'rgba(0, 0, 255, 1)';
// c.fillRect(400, 100, 100, 100);
// c.fillStyle = 'rgba(0, 255, 0, 1)';
// c.fillRect(300, 300, 100, 100);
// console.log(canvas);

//Line

// c.beginPath();
// c.moveTo(50,300);
// c.lineTo(300,100);
// c.strokeStyle = 'rgba(0, 0, 255, 1)';
// c.stroke();

//Arc 

//c.beginPath();
//c.arc(300, 300, 30, 0, Math.PI * 2, false);
//c.strokeStyle = 'red';
//c.stroke();

// for (var i = 0; i < 10; i++) {
// 	var x = Math.random() * window.innerWidth;
// 	var y = Math.random() * window.innerHeight;
// 	c.beginPath();
// 	c.arc(x, y, 30, 0,  Math.PI * 2, false);
	
// 	//c.fillStyle = 'rgba(0, 255, 0, 0.5)';
// 	//c.fill();
// 	c.strokeStyle = 'red';
// 	c.stroke();
// }

var mouse = {

	x: undefined,
	y: undefined

}

var maxRadius = 40;
//var minRadius = 2;

var colorArray = [
	'#4166f5',
	'#00bfff',
	'#11ff00',
	'#55dddd',
	'#0d98ba',
];

console.log(colorArray.length);

window.addEventListener('mousemove', function(event) {
	mouse.x = event.x;
	mouse.y = event.y;





})

window.addEventListener('resize', function() 
	{

	canvas.width = window.innerWidth;
	canvas.height = window.innerHeight;

	init();



});

function Circle(x, y, dx, dy, radius) {
	this.x = x;
	this.y = y;
	this.dx = dx;
	this.dy = dy;
	this.radius = radius;
	this.minRadius = radius;
	this.color = colorArray[Math.floor(Math.random() * colorArray.length)];

	this.draw = function() {
		c.beginPath();
	
		c.arc(this.x, this.y, this.radius, 30, 0, Math.PI * 2, false);
		c.fillStyle = this.color;
		c.fill();
		
	}

	this.update = function() {
		if (this.x  + this.radius > innerWidth || this.x - this.radius < 0) {
		this.dx = -this.dx;

	}

	if (this.y + this.radius > innerHeight || this.y - this.radius < 0) {
		this.dy = -this.dy;
	}

	this.x += this.dx;
	this.y += this.dy;

	//interactivity

	if (mouse.x - this.x < 50 && mouse.x - this.x > -50
		&& mouse.y - this.y < 50 && mouse.y - this.y > -50 


		) {
		if (this.radius < maxRadius) {
			this.radius += 1;
		}
		this.radius += 1;
	} else if (this.radius > this.minRadius) {
		this.radius -= 1;
	}



	this.draw();



	}

}



var circleArray =[];



function init() {

	circleArray = [];

	for (var i = 0; i < 1000; i++) {
		var radius = Math.random() * 3 + 1;
		var x = Math.random() * (innerWidth - radius * 2) + radius;
		var y = Math.random() * (innerHeight - radius * 2) + radius;
		var dx = (Math.random() - 0.5); 
		var dy = (Math.random() - 0.5); 

		circleArray.push(new Circle(x, y, dx, dy, radius));


	}


}

function animate() {
	requestAnimationFrame(animate);
	c.clearRect(0,0, innerWidth, innerHeight);


	for (var i = 0; i < circleArray.length; i++) {
		circleArray[i].update();




	}


	
	
	
}

init();

animate();


Drawing script

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;


window.addEventListener('resize', function() 
	{

	

	init();



});
var radius = 5;
var dragging = false;

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

context.lineWidth = radius*2;

var putPoint = function(e) {
	if(dragging){
		context.lineTo(e.clientX, e.clientY);
		context.strokeStyle = '#55dddd';
		context.stroke();
		context.beginPath();
		context.arc(e.clientX, e.clientY, radius, 8, Math.PI*2);
		context.fillStyle = '#55dddd';
		context.fill();
		context.beginPath();
		context.moveTo(e.clientX, e.clientY);
	}
}

var engage = function(e){
	dragging = true;
	putPoint(e);
}

var disengage = function(){
	dragging = false;
	context.beginPath();

}


canvas.addEventListener('mousedown', engage);
canvas.addEventListener('mousemove', putPoint);
canvas.addEventListener('mouseup', disengage);




ThreeJs



To be understand the use of the 3D in JavaScript I had to dive in to some theory of the system how it is build up. Having 3D experience from Cinem4D it helped a bit to get familiar with ThreeJs. Very useful sites were the following ones: theory + tutorial

Three.js is a Javascript library developed by Ricardo Cabello (@mrdoob) in 2010 (today it has many contributors on Github). This incredible tool let us work with 3D graphics on the browser, using WebGL in a very simple and intuitive way.


The renderer is the place where the result of the scene will be visible. In Three.js we can have multiple scenes and each one can have different objects.


In Three.js a Mesh is the composition of a Geometry with a Material.


A Geometry is the mathematical formula of an object, in Three.js we have many geometries, we’ll explore it in future chapters. A Geometry give us the vertices of the object we want to add to the scene.


A Material can be defined as the properties of an object and its behavior with the light sources of the scene. As you can see in the following image there are different types of materials.



Console became my friend after time...Debugging, debugging, debugging...


ThreeJs exploration



<!DOCTYPE html>

<html>
<body>
	<script src="three.min.js"></script>
	<script src="TrackballControls.js"></script>

	<script>
		var camera, controls, scene, renderer;

		init();
		animate();

		function init(){

			camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
			camera.position.z = 500;

			controls = new THREE.TrackballControls( camera );
			controls.addEventListener('change', render);

			scene = new THREE.Scene();

			var geometry = new THREE.CubeGeometry(100, 100, 100);

			var material = new THREE.MeshNormalMaterial();

			var mesh = new THREE.Mesh( geometry, material );
			scene.add(mesh);

			renderer = new THREE.WebGLRenderer();
			renderer.setSize(window.innerWidth,  window.innerHeight);

			document.body.appendChild(renderer.domElement);
		}

		function animate() {
			requestAnimationFrame( animate );
			controls.update();
		}

		function render(){

			renderer.render( scene, camera );

		}

	</script>

</body>
</html>

Blocks




<!DOCTYPE html>

<html>

<head>
	<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script> -->
	<title> Simple Three.js</title>

	<style>
	body {
		margin: 0;
		overflow: hidden;
	}
	</style>
</head>

<body>
	<canvas id="Canvas"></canvas>
	<script src="three.min.js"></script>
	<script src="TrackballControls.js"></script>


	<script>
		var renderer, camera, scene, light, light1, geometry, material, mesh;

		//renderer

		renderer = new THREE.WebGLRenderer({canvas: 
		document.getElementById('Canvas'), antialias: true});
		renderer.setClearColor(0x000000);
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(window.innerWidth, window.innerHeight);

		//camera

		camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 30000);


		controls = new THREE.TrackballControls( camera );
		controls.addEventListener('change', render);
	

		//scene

		scene = new THREE.Scene();

		//light

		light = new THREE.AmbientLight(0xffffff, 0.5);
		light1 = new THREE.PointLight(0xffffff, 0.1);
		scene.add(light, light1);

		var allmesh = [];
		//object

		for (var i=0, l = 1; i<l; i++) {
			geometry = new THREE.BoxGeometry(239, 162, 88);
			material = new THREE.MeshLambertMaterial({
				color: '#489000',
			});
			mesh = new THREE.Mesh(geometry, material);

			//scene.add(mesh);
			//mesh.position.set(500, 100, 100);
			mesh.position.set(Math.random()*100, Math.random()*100, -500);
			scene.add(mesh);
			var speed = Math.random() * 0.005;
			allmesh.push({mesh: mesh, speed: speed});

		}

 
		for (var i=0, l = 1; i<l; i++) {
			geometry = new THREE.BoxGeometry(289, 300, 206);
			material = new THREE.MeshLambertMaterial({
				color: '#1595',
			});
			mesh = new THREE.Mesh(geometry, material);
			mesh.position.set(Math.random()*10, Math.random()*200, -600, 400);
			scene.add(mesh);
			var speed = Math.random() * 0.005;
			allmesh.push({mesh: mesh, speed: speed}); 

		}

		for (var i=0, l = 1; i<l; i++) {
			geometry = new THREE.BoxGeometry(100, 100, 100);
			material = new THREE.MeshLambertMaterial({
				color: '#99FFCC',
			});
			mesh = new THREE.Mesh(geometry, material);
			mesh.position.set(Math.random()*100, Math.random()*100, -500);
			scene.add(mesh);
			var speed = Math.random() * 0.005;
			allmesh.push({mesh: mesh, speed: speed});

		}

		for (var i=0, l = 1; i<l; i++) {
			geometry = new THREE.BoxGeometry(10, 10, 100);
			material = new THREE.MeshLambertMaterial({
				color: '#99FFCC',
			});
			mesh = new THREE.Mesh(geometry, material);
			mesh.position.set(Math.random()*100, Math.random()*100, -100);
			scene.add(mesh);
			var speed = Math.random() * 0.005;
			allmesh.push({mesh: mesh, speed: speed});

		}

		var light = new THREE.DirectionalLight('white');
		light.position.set(2,2,2).normalize();
		scene.add(light);

		//render loop
		requestAnimationFrame(render);

		function animate() {
			requestAnimationFrame( animate );
			controls.update();
		}

		function render() {
			for (var i=0, l=allmesh.length; i<l; i++) {
				allmesh[i].mesh.rotation.x += allmesh[i].speed;
				allmesh[i].mesh.rotation.y += allmesh[i].speed;
			}
			//mesh.rotation.x += 0.01;
			//mesh.rotation.y += 0.01;
			renderer.render(scene, camera);
			requestAnimationFrame(render);
		}


	</script>

</body>
</html>



Shapes generated based on ASCII numeric values

JS Fiddle to the script



HTML


<!DOCTYPE html>
<html>

<head>
	<title>XPPL VOLUMETRIC CATALOGUE </title>
	<meta charset="utf-8">
	<link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<style>
		body{
			cccccc;
				font-family: 'Karla', sans-serif;
				font-size:15px;

				text-align:left;
				background-color: #140b33;
				margin: 0px;
				overflow: hidden;
			}
			#info {
				position: absolute;
				top: 0px; width: 10%;
				padding: 10px;
			}
			a {
				color: #444b7c;
			}

	</style>
</head>
<body>
	<canvas id="viewer"></canvas> 
	<div id="info"><a  target="_blank" rel="noopener">XPPL VOLUMETRIC CATALOGUE  <br> <br> Feel free to move around and explore the content of the library by clicking on the volumetric shapes</div>
	<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script>
	<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>
	<script src="Raycaster.js"></script>
	<script src="setup8.js"></script>
		

</body>
</html>



JS


const MAX_DISTANCE = 12000;
const MAX_SPHERE_RADIUS = 700;

let camera, scene, controls, renderer, material;

console.clear();
let bookTitles = [{
    title: "Mac OS X Leopard Edition",
    id: "1",
    type: 'sphere'
  },
  {
    title: "The Qmail Handbook",
    id: "2",
    type: 'sphere'
  },
  {
    title: "Hardening Network Infrastructure: Bulletproof Your Systems Before You Are Hacked!",
    id: "3",
    type: 'sphere'
  },
  {
    title: "Cocoa Programming for Mac OS X Second Edition",
    id: "4",
    type: 'sphere'
  },
  {
    title: "LDAP System Administration",
    id: "5",
    type: 'sphere'
  },
  {
    title: "Learning Unix for Mac OS X",
    id: "6",
    type: 'sphere'
  },
  {
    title: "Mac OS X Panther for Unix Geeks",
    id: "7",
    type: 'sphere'
  },
  {
    title: "Linux System Administration",
    id: "8",
    type: 'sphere2'
  },
  {
    title: "Managing and Using MYSQL",
    id: "9",
    type: 'sphere'
  },
  {
    title: "MYSQL In a Nutshell",
    id: "10",
    type: 'sphere2'
  },
  {
    title: "Actionscript for Flash MX: The Definitive Guide",
    id: "11",
    type: 'sphere2'
  },
  {
    title: "Programming Firefox",
    id: "12",
    type: 'sphere'
  },
  {
    title: "Learning PHP and MYSQL",
    id: "13",
    type: 'sphere'
  },
  {
    title: "Learning the Bash Shell",
    id: "14",
    type: 'sphere2'
  },
  {
    title: "GNU Emacs Pocket Reference",
    id: "15",
    type: 'sphere'
  },
  {
    title: "SQL Pocket Guide",
    id: "16",
    type: 'sphere2'
  },
  {
    title: "HTML Pocket Reference",
    id: "17",
    type: 'sphere2'
  },
  {
    title: "Regular Expression Pocket Reference",
    id: "18",
    type: 'sphere2'
  },
  {
    title: "Apache 2 Pocket Reference",
    id: "19",
    type: 'sphere'
  },
  {
    title: "CSS Pocket Reference",
    id: "20",
    type: 'sphere2'
  },
  {
    title: "vi Editor Pocket Reference",
    id: "21",
    type: 'sphere2'
  },
  {
    title: "The Book of Inkscape",
    id: "22",
    type: 'sphere'
  },
  {
    title: "Working with Mediawiki",
    id: "23",
    type: 'sphere2'
  },
  {
    title: "Beginning Game Development with Python and Pygame",
    id: "24",
    type: 'sphere'
  },
  {
    title: "Game Programming with Python, Lua, and Ruby 1 edition",
    id: "25",
    type: 'sphere2'
  },
  {
    title: "Data Modeling for Everyone",
    id: "26",
    type: 'sphere'
  },
  {
    title: "The Ultimate Guide to the Vi and Ex Text Editors",
    id: "27",
    type: 'sphere2'
  },
  {
    title: "Getting Gread Sounds: The Microphone Book",
    id: "28",
    type: 'sphere2'
  },
  {
    title: "How to Think Like a Computer Scientist",
    id: "29",
    type: 'sphere2'
  },
  {
    title: "Python Pocket Reference",
    id: "30",
    type: 'sphere2'
  },
  {
    title: "Things That Talk",
    id: "31",
    type: 'sphere2'
  },
  {
    title: "The Social Construction of What?",
    id: "32",
    type: 'sphere2'
  },
  {
    title: "Instruments and the Imagination",
    id: "33",
    type: 'sphere'
  },
  {
    title: "Mind, Machines and Human Consciousness",
    id: "34",
    type: 'sphere2'
  },
  {
    title: "The Psychopath Test",
    id: "35",
    type: 'sphere2'
  },
  {
    title: "The Selfish Gene",
    id: "36",
    type: 'sphere2'
  },
  {
    title: "Pandora's Hope",
    id: "37",
    type: 'sphere2'
  },
  {
    title: "The New Spirit of Capitalism",
    id: "38",
    type: 'sphere'
  },
  {
    title: "Distinction: A Social Critique of the Judgement of Taste",
    id: "39",
    type: 'sphere'
  },
  {
    title: "The Political Economy of Media: Enduring Issues, Emerging Dilemmas",
    id: "40",
    type: 'sphere'
  },
  {
    title: "The Dustbin of History",
    id: "41",
    type: 'sphere'
  },
  {
    title: "Inventing The Victorians",
    id: "42",
    type: 'sphere1'
  },
  {
    title: "Age of the Extremes: The Short Twentieth Century 1914-1991",
    id: "43",
    type: 'sphere1'
  },
  {
    title: "Lipstick Traces",
    id: "44",
    type: 'sphere1'
  },
  {
    title: "False Dawn: The Delusions of Global Capitalism",
    id: "45",
    type: 'sphere1'
  },
  {
    title: "Debt: The First 5000 Years",
    id: "46",
    type: 'sphere1'
  },
  {
    title: "Georges Bataille: An Intellectual Biography",
    id: "47",
    type: 'sphere1'
  },
  {
    title: "The Enlightenment Reader",
    id: "48",
    type: 'sphere2'
  },
  {
    title: "The Century",
    id: "49",
    type: 'sphere2'
  },
  {
    title: "Rethinking Media Pluralism",
    id: "50",
    type: 'sphere2'
  },
  {
    title: "The Philosophy of Symbolic Forms",
    id: "51",
    type: 'sphere'
  },
  {
    title: "Archaeology",
    id: "52",
    type: 'sphere1'
  },
  {
    title: "The Chomsky Reader",
    id: "53",
    type: 'sphere1'
  },
  {
    title: "The Society of Mind",
    id: "54",
    type: 'sphere1'
  },
  {
    title: "Interference: A Grand Scientific Musical Theory",
    id: "55",
    type: 'sphere1'
  },
  {
    title: "Understanding media economics",
    id: "56",
    type: 'sphere1'
  },
  {
    title: "Convergence culture",
    id: "57",
    type: 'sphere1'
  },
  {
    title: "Digital Labor",
    id: "58",
    type: 'sphere1'
  },
  {
    title: "The culture of connectivity",
    id: "59",
    type: 'sphere1'
  },
  {
    title: "Anti-Media",
    id: "60",
    type: 'sphere1'
  },
  {
    title: "Holding On to Reality: The Nature of Information at the Turn of the Millennium",
    id: "61",
    type: 'sphere1'
  },
  {
    title: "Organized Networks",
    id: "62",
    type: 'sphere1'
  },
  {
    title: "Over Mediatheorie",
    id: "63",
    type: 'sphere'
  },
  {
    title: "Post Truth",
    id: "64",
    type: 'sphere'
  },
  {
    title: "Weapons of Math Destruction",
    id: "65",
    type: 'sphere'
  },
  {
    title: "Media Ecologies: Materialist Energies in Art and Technoculture",
    id: "66",
    type: 'sphere'
  },
  {
    title: "The Internet Is Not The Answer",
    id: "67",
    type: 'sphere2'
  },
  {
    title: "Wired for war - Robotics revolution and conflict in the 21st century",
    id: "68",
    type: 'sphere'
  },
  {
    title: "Interface Culture",
    id: "69",
    type: 'sphere2'
  },
  {
    title: "The Interface Effect",
    id: "70",
    type: 'sphere'
  },
  {
    title: "Present Shock: When Everything Happens Now",
    id: "71",
    type: 'sphere'
  },
  {
    title: "Bastard Culture!: How User Participation Transforms Cultural Production",
    id: "72",
    type: 'sphere2'
  },
  {
    title: "Media Virus! Hidden Agendas in Popular Culture",
    id: "73",
    type: 'sphere'
  },
  {
    title: "Loving Big Brother: Surveillance Culture and Performance Space",
    id: "74",
    type: 'sphere3'
  },
  {
    title: "Selections from Cultural Writings",
    id: "75",
    type: 'sphere2'
  },
  {
    title: "Dark Money: The Hidden History of the Billionairs behind the Rise of the Radical Right",
    id: "76",
    type: 'sphere3'
  },
  {
    title: "Walter Benjamin for beginners",
    id: "77",
    type: 'sphere3'
  },
  {
    title: "What is Situationism? A Reader",
    id: "78",
    type: 'sphere'
  },
  {
    title: "Cyburbia",
    id: "79",
    type: 'sphere'
  },
  {
    title: "Mondothèque a radiated book/un livre irradiant/een irradiërend boek",
    id: "80",
    type: 'sphere3'
  },
  {
    title: "Save and Forget",
    id: "81",
    type: 'sphere3'
  },
  {
    title: "The World Explained",
    id: "82",
    type: 'sphere3'
  },
  {
    title: "Information - Documents of Contemporary Art",
    id: "83",
    type: 'sphere3'
  },
  {
    title: "Postscript on the Societies of Control",
    id: "84",
    type: 'sphere3'
  },
  {
    title: "Ethics Subjectivity and Truth",
    id: "85",
    type: 'sphere2'
  },
  {
    title: "The Infinite Conversation",
    id: "86",
    type: 'sphere'
  },
  {
    title: "Identity and Difference",
    id: "87",
    type: 'sphere'
  },
  {
    title: "Jean Paul A Reader",
    id: "88",
    type: 'sphere'
  },
  {
    title: "The Ear of the Other",
    id: "89",
    type: 'sphere'
  },
  {
    title: "Statements on Appropriation (London Version)",
    id: "90",
    type: 'sphere2'
  },
  {
    title: "An Introduction to Western Philosophy",
    id: "91",
    type: 'sphere'
  },
  {
    title: "The Postmodern Turn",
    id: "92",
    type: 'sphere'
  },
  {
    title: "Ideology",
    id: "93",
    type: 'sphere'
  },
  {
    title: "Ludwig Wittgenstein",
    id: "94",
    type: 'sphere2'
  },
  {
    title: "The Human Condition",
    id: "95",
    type: 'sphere'
  },
  {
    title: "Introducing Foucault",
    id: "96",
    type: 'sphere'
  },
  {
    title: "The Lives of Michel Foucault",
    id: "97",
    type: 'sphere'
  },
  {
    title: "Discipline and Punish",
    id: "98",
    type: 'sphere'
  },
  {
    title: "Logic of Scientific Discovery",
    id: "99",
    type: 'sphere'
  },
  {
    title: "Intensive Science and Virtual Philosophy",
    id: "100",
    type: 'sphere2'
  },
  {
    title: "Kant and the Platypus: Essays on Language and Cognition",
    id: "101",
    type: 'sphere'
  },
  {
    title: "Turning Back the Clock",
    id: "102",
    type: 'sphere'
  },
  {
    title: "Travels in hyper reality : essays",
    id: "103",
    type: 'sphere'
  },
  {
    title: "On revolution",
    id: "104",
    type: 'sphere3'
  },
  {
    title: "Introducing Kant",
    id: "105",
    type: 'sphere3'
  },
  {
    title: "The Perfect Crime",
    id: "106",
    type: 'sphere3'
  },
  {
    title: "Introducing Baudrillard",
    id: "107",
    type: 'sphere1'
  },
  {
    title: "The structure of scientific revolutions",
    id: "108",
    type: 'sphere3'
  },
  {
    title: "The World Turned Upside Down: Radical Ideas During the English Revolution",
    id: "109",
    type: 'sphere1'
  },
  {
    title: "On Wine and Hishish",
    id: "110",
    type: 'sphere1'
  },
  {
    title: "Lacan For Beginners",
    id: "111",
    type: 'sphere3'
  },
  {
    title: "Late Marxism",
    id: "112",
    type: 'sphere1'
  },
  {
    title: "Adorno",
    id: "113",
    type: 'sphere1'
  },
  {
    title: "Dialectic of Enlightenment",
    id: "114",
    type: 'sphere3'
  },
  {
    title: "Walter Benjamin: A Biography",
    id: "115",
    type: 'sphere1'
  },
  {
    title: "A Thousand Years of Nonlinear History",
    id: "116",
    type: 'sphere3'
  },
  {
    title: "Barthes: Selected Writings",
    id: "117",
    type: 'sphere3'
  },
  {
    title: "Camera Lucida: Reflections on Photography",
    id: "118",
    type: 'sphere1'
  },
  {
    title: "Derrida For Beginners",
    id: "119",
    type: 'sphere1'
  },
  {
    title: "System and Writing in the Philosophy of Jacques Derrida",
    id: "120",
    type: 'sphere1'
  },
  {
    title: "Exploring Humans",
    id: "121",
    type: 'sphere2'
  },
  {
    title: "Urheberrecht im Alltag: Kopieren, bearbeiten, selber machen",
    id: "122",
    type: 'sphere3'
  },
  {
    title: "DATA browser 02: Engineering Culture",
    id: "123",
    type: 'sphere1'
  },
  {
    title: "DATA browser 01: Economising Culture",
    id: "124",
    type: 'sphere1'
  },
  {
    title: "The Mag.net reader 3, Processual Publishing. Actual Gesture",
    id: "125",
    type: 'sphere'
  },
  {
    title: "New Media Art",
    id: "126",
    type: 'sphere1'
  },
  {
    title: "Digital Prohibition",
    id: "127",
    type: 'sphere1'
  },
  {
    title: "The Cathedral & The Bazaar",
    id: "128",
    type: 'sphere3'
  },
  {
    title: "The Code Book",
    id: "129",
    type: 'sphere1'
  },
  {
    title: "DiY Survival // There is No Subculture Only Subversion",
    id: "130",
    type: 'sphere3'
  },
  {
    title: "Guide to Open Content Licenses",
    id: "131",
    type: 'sphere3'
  },
  {
    title: "DATA browser 3: Curating Immateriality",
    id: "132",
    type: 'sphere3'
  },
  {
    title: "Formen interaktiver Medienkunst",
    id: "133",
    type: 'sphere3'
  },
  {
    title: "Oulipo Compendium",
    id: "134",
    type: 'sphere3'
  },
  {
    title: "Convergence: The International Journal of Research into New Media Technologies - Volume 12 Number 3 August 2004",
    id: "135",
    type: 'sphere1'
  },
  {
    title: "Perl for Web Site Management",
    id: "136",
    type: 'sphere1'
  },
  {
    title: "Seven Hundred Penguins",
    id: "137",
    type: 'sphere3'
  },
  {
    title: "Mondotheque: a radiated book / un livre irradiant / een iradierend boek",
    id: "138",
    type: 'sphere1'
  },
  {
    title: "An Atlas of Typeforms",
    id: "139",
    type: 'sphere'
  },
  {
    title: "Structure of the Visual Book",
    id: "140",
    type: 'sphere3'
  },
  {
    title: "The Uses of Literacy",
    id: "141",
    type: 'sphere1'
  },
  {
    title: "Control and Freedom: Power and Paranoia in the Age of Fiber Optics",
    id: "142",
    type: 'sphere2'
  },
  {
    title: "The New Media Reader",
    id: "143",
    type: 'sphere1'
  },
  {
    title: "Art and Electronic Media",
    id: "144",
    type: 'sphere3'
  },
  {
    title: "The Situationist City",
    id: "145",
    type: 'sphere1'
  },
  {
    title: "The Absolute Report: Time Space Code Memory",
    id: "146",
    type: 'sphere3'
  },
  {
    title: "Ashes and Broken Brickwork of a Logical Theory",
    id: "147",
    type: 'sphere3'
  },
  {
    title: "Surrealist Painters and Poets: An Anthology",
    id: "148",
    type: 'sphere3'
  },
  {
    title: "Guy Debord and the Situationists International",
    id: "149",
    type: 'sphere1'
  },
  {
    title: "A Bed a Chair and a Table",
    id: "150",
    type: 'sphere3'
  },
  {
    title: "Software Studies a lexicon",
    id: "151",
    type: 'sphere3'
  },
  {
    title: "The Rise of the Network Society, With a New Preface: Volume I: The Information Age: Economy, Society, and Culture (Information Age Series)",
    id: "152",
    type: 'sphere3'
  },
  {
    title: "I Read Where I Am: Exploring New Information Cultures",
    id: "153",
    type: 'sphere3'
  },
  {
    title: "Present Continuous Past(s): Media Art. Strategies of Presentation, Mediation and Dissemination",
    id: "154",
    type: 'sphere1'
  },
  {
    title: "exquisite_code",
    id: "155",
    type: 'sphere1'
  },
  {
    title: "Uncreative Writing",
    id: "156",
    type: 'sphere3'
  },
  {
    title: "The Electronic Revolution",
    id: "157",
    type: 'sphere2'
  },
  {
    title: "The Invisible Generation",
    id: "158",
    type: 'sphere3'
  },
  {
    title: "Cybernetics & Ghosts",
    id: "159",
    type: 'sphere1'
  },
  {
    title: "Digital (Steve Trim 2 reading)",
    id: "160",
    type: 'sphere1'
  },
  {
    title: "A Preface to Plato",
    id: "161",
    type: 'sphere3'
  },
  {
    title: "Writing Machines",
    id: "162",
    type: 'sphere3'
  },
  {
    title: "Gramophone, Film, Typewriter",
    id: "163",
    type: 'sphere3'
  },
  {
    title: "Literature Media",
    id: "164",
    type: 'sphere1'
  },
  {
    title: "iSpace: Printed English after Joyce, Shannon, Derrida",
    id: "165",
    type: 'sphere1'
  },
  {
    title: "Orality and Literacy",
    id: "166",
    type: 'sphere2'
  },
  {
    title: "International Picture Language",
    id: "167",
    type: 'sphere1'
  },
  {
    title: "Protocol",
    id: "168",
    type: 'sphere1'
  },
  {
    title: "A Prehistory of the Cloud",
    id: "169",
    type: 'sphere1'
  },
  {
    title: "Paratexts: Thresholds of Interpretation",
    id: "170",
    type: 'sphere1'
  }
];

var raycaster = new THREE.Raycaster(),
  INTERSECTED;
var mouse = new THREE.Vector2();

//mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
//mouse.y = -(event.clientY/ window.innerHeight) * 2 + 1;

let objects = [];

function setupBooks() {
  bookTitles.forEach(book => {
    let geometry;
    let material;
    let radius = Math.floor(Math.random() * MAX_SPHERE_RADIUS);
    switch (book.type) {
      case 'sphere':
        geometry = new THREE.SphereGeometry(radius, 3, 30);
        break;
      case 'sphere1':
        geometry = new THREE.SphereGeometry(radius, 5, 3);
        break;
      case 'sphere2':
        geometry = new THREE.SphereGeometry(radius, 10, 10);
        break;
      case 'sphere3':
        geometry = new THREE.SphereGeometry(radius, 1, 1);
        break;
      case 'cone':
        geometry = new THREE.ConeGeometry(radius, radius, radius, radius, 50, 50);
        break;
      case 'cylinder':
        geometry = new Cylinder.BoxGeometry(radius, radius, radius, 10, 10);
        break;
      case 'cube':
        geometry = new THREE.BoxGeometry(radius, radius, radius, 10, 10);
        break;

    }

    material = new THREE.MeshPhongMaterial({
      color: Math.random() * 0xff00000 - 0xff00000
    });

    material.flatShading = true;

    // Add missing material
    let mesh = new THREE.Mesh(geometry, material);
    mesh.speed = Math.random() * 0.05;

    mesh.position.copy(getRandomVector(MAX_DISTANCE));

    objects.push(mesh);

    scene.add(mesh);
  });
}

function createSpace() {
  let dots = new THREE.Object3D();

  for (var i = 0; i < 10000; i++) {
    var circleGeometry = new THREE.SphereGeometry(50, Math.random() * 5, Math.random() * 5);
    var material = new THREE.MeshBasicMaterial({
      color: Math.random() * 0xff00000 - 0xff00000,
      side: THREE.DoubleSide
    });
    material.flatShading = true;

    var circle = new THREE.Mesh(circleGeometry, material);

    let direction = getRandomVector().normalize();
    let minDistance = MAX_DISTANCE * 5;
    let maxDistance = minDistance + 0.5;
    direction.multiplyScalar(Math.random() * (maxDistance - minDistance) + minDistance);

    circle.position.add(direction);

    dots.add(circle);
  }

  scene.add(dots);
}

function onMouseMove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  mouseX = event.clientX - window.innerWidth / 2;
  mouseY = event.clientY - window.innerHeight / 2;
  camera.position.x += (mouseX - camera.position.x) * 0.01;
  camera.position.y += (mouseY - camera.position.y) * 0.01;
  camera.lookAt(scene.position);
}

function getRandomVector(max_distance) {
  if (max_distance === undefined)
    max_distance = 1;
  return new THREE.Vector3(getRandom(max_distance), getRandom(max_distance), getRandom(max_distance));
}

function getRandom(max_distance) {
  let random = Math.random() * max_distance;
  random *= Math.floor(Math.random() * 2) == 1 ? 1 : -1;
  return random;
}

function animate() {
  requestAnimationFrame(animate);
  if (controls.enableDamping) {
    controls.update();
  }

  objects.forEach(object => {
    object.rotation.y += object.speed;
  });

  render();
}

function render() {
  renderer.render(scene, camera);
}

function init() {
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x140b33);

  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 300000);
  camera.position.set(MAX_DISTANCE, MAX_DISTANCE, MAX_DISTANCE);
  camera.updateProjectionMatrix();

  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.maxDistance = MAX_DISTANCE * 3;
  controls.target = new THREE.Vector3(0, 0, 0);
  controls.rotateSpeed = .2;
  controls.enableDamping = true;
  console.log(controls.enableDamping);
  controls.dampingFactor = .15;
  controls.panSpeed = .15;
  controls.screenSpacePanning = true;

  scene.add(camera);

  scene.add(new THREE.DirectionalLight(0xffffff));
  scene.add(new THREE.DirectionalLight(0x002288));
  scene.add(new THREE.AmbientLight(0x222222));

  renderer.setPixelRatio(window.devicePixelRatio);

  let viewer = document.querySelector('#viewer');
  viewer.parentNode.replaceChild(renderer.domElement, viewer);
}

init();
animate();
createSpace();
setupBooks();

window.onresize = function() {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
};


Final working script


The string values of the titles and the metadata from the JSON file is generating the radius and the position of the shapes



<!DOCTYPE html>

<html>
<head>
    <title>XPPL VOLUMETRIC CATALOGUE </title>
    <meta charset="utf-8">
    <link href="https://fonts.googleapis.com/css?family=Karla" rel="stylesheet">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body{
            
                font-family: 'Karla', sans-serif;
                font-size:15px;

                text-align:left;
                background: #140b33;
                margin: 0px;
                overflow: hidden;
            }
            #info {
                position: absolute;
                top: 0px; width: 10%;
                padding: 10px;
            }
            a {
                color: #444b7c;
            }

            .swal-button {
                padding: 7px 19px;

                background-color: #aca4c1;
                font-size: 12px;


}

            .swal-title {
                margin: 0px;
                font-size: 16px;
                box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.21);
                margin-bottom: 28px;
}

            .swal-overlay {
                background-color: rgba(20, 13, 50, 0.6);
}
            .swal-modal {
                background-color: rgba(172, 164, 193, 1);

}



    </style>
</head>
<body>
    <div id="info"><a  target="_blank" rel="noopener"> <b> <font size="5"> XPPL VOLUMETRIC CATALOGUE </font> </b> <br>  <br> Feel free to move around and explore the content of the library by clicking on the volumetric shapes</div>
    <div id="container"></div>
    <canvas id="viewer"></canvas>
    <script src="https://rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script>
    <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>
    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script>


var category2color = new Object();
category2color["Technical"] = "#003d5d";
category2color["Science/History"] = "#f23d5d";
category2color["Media studies"] = "#8c3d5d";
category2color["Philosophy"] = "#723d5d";
category2color["Computer culture"] = "#423d5d";
category2color["Design / writing / publishing"] = "#ff0000";
category2color["Desk"] = "#09edff";
category2color["Art"] = "#ffedff";
category2color["Digital (Steve Trim 2 reading)"] = "#ffe1cc";
category2color["Media Studies (Femke Trim 3)"] = "#00e1cc";
category2color["Literature, Culture, Theory"] = "#00a1d4";

category2color["default"] = "#cdc1ec";




        console.clear();

const MAX_DISTANCE = 1000;
//
const MIN_DISTANCE = 200;

const MAX_SPHERE_RADIUS = 700;

var bookTitles;
var request = new XMLHttpRequest();
request.open('GET', 'export.json', true);

request.onload = function() {
  if (request.status >= 200 && request.status < 400) {
    var data = JSON.parse(request.responseText);
    //bookTitles = data;
    bookTitles = data.books[0];

    bookTitles.forEach(function(book) {
      book.type = "sphere";
      console.log('BOOK:', book);



    });
    console.log("got books", bookTitles)
    // loaded data, start
    init();
    animate();

  } else {
    // We reached our target server, but it returned an error

  }
};

request.onerror = function() {
  // There was a connection error of some sort
};

request.send();


// --- threeJS --- //
var renderer, scene, camera, distance, raycaster, projector;

var container = document.getElementById('container');
var raycaster = new THREE.Raycaster(),INTERSECTED;
var mouse = new THREE.Vector2();
var distance = 600;

// -- basic initialization -- //
function init() {
    renderer = new THREE.WebGLRenderer({
        antialias: true
    });


    renderer.setClearColor(0x140b33, 1);
    //renderer.setClearColor(0xFF00FF, 1.0);
    renderer.setSize(window.innerWidth, window.innerHeight);
    container.appendChild(renderer.domElement);
    renderer.clear();
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 300000);
  //  controls = new THREE.OrbitControls(camera);
    //camera.position.set(1, 1, -5);
    camera.position.set(MAX_DISTANCE/2, MAX_DISTANCE/20, MAX_DISTANCE/20);

    camera.updateProjectionMatrix();

    controls = new THREE.OrbitControls(camera, renderer.domElement);
  //  controls.maxDistance = MAX_DISTANCE * 3;
    controls.target = new THREE.Vector3(0, 0, 0);
    controls.rotateSpeed = .2;
    controls.enableDamping = true;
    console.log(controls.enableDamping);
    controls.dampingFactor = .15;
    controls.panSpeed = .15;
    controls.screenSpacePanning = true;
    // to disable zoom
    controls.enableZoom = true;
    // to disable rotation
    controls.enableRotate = true;
    // to disable pan
    controls.enablePan = true;
    scene.add(camera);

    //camera.position.set(-150, 10, 1);
    //controls.update();
   // scene.add(camera);

    light = new THREE.PointLight(0x404040);
    light.position.set(50, 0, 0);
    scene.add(light);
   /* light_two = new THREE.PointLight(0xffffff, 1, 4000);
    light_two.position.set(-100, 800, 800);
    lightAmbient = new THREE.AmbientLight(0x404040);
    scene.add(light, light_two, lightAmbient);*/

    // createSpheres();
    scene.add(new THREE.DirectionalLight(0xffffff));
    scene.add(new THREE.AmbientLight(0x222222));

    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.clear();

    let viewer = document.querySelector('#viewer');
    viewer.parentNode.replaceChild(renderer.domElement, viewer);

    


window.onload = function () {

    createDiamond();
    createSpace();
    

    document.addEventListener('mousemove', onMouseMove, false);
    document.addEventListener('mousedown', onDocumentMouseDown, false);
    window.addEventListener('resize', onWindowResize, false);
};


}

// -- diamonds -- //


function catInobject(obj, category){ //checks if category is in object, if so return corresponding color
    if (obj.hasOwnProperty(category)) {
    var color = obj[category];
    } else { var color = obj["default"];
 }
    return color;
}

function createDiamond() {

    diamondsGroup = new THREE.Object3D();


        console.log();

        bookTitles.forEach(function (book) {
            var chosencolor = catInobject(category2color, book.category);
            var sphere = new THREE.SphereGeometry(1.3, Math.random() * 50, Math.random() * 50);
            var material = new THREE.MeshPhongMaterial({
                color: chosencolor,//Math.random() * 0xff00000 - 0xff00000,
                shading: THREE.FlatShading
            });
            var sphere = new THREE.Mesh(sphere, material);
            sphere.position.x = get_x(book.title) * Math.random() * 100 - 1000;
            sphere.position.z = get_z(book.category) * Math.random() *  100 - 1000;
            sphere.rotation.y =get_y(book.fileformat) * Math.random() * 100 - 1000;
            //sphere.scale.x = sphere.scale.y = sphere.scale.z = Math.random() * 50 + 10;
            sphere.scale.x = sphere.scale.y = sphere.scale.z = get_size(book.title);

            sphere.userData = book;
            diamondsGroup.add(sphere);

        })
        diamondsGroup.position.x = 500;
        scene.add(diamondsGroup);

};

function get_size(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}

function get_x(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}
function get_y(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}
function get_z(title){
    radius = 0;
    for (var i = 0; i < title.length; i++) {
      radius = radius + title.charCodeAt(i)
    }
    console.log(radius)
    return radius/100;
}

// -- dots on the back -- //
function createSpace() {

    let dots = new THREE.Object3D();

    for (let i = 0; i < 1000; i++) {
        let circleGeometry = new THREE.SphereGeometry(2, Math.random() * 5, Math.random() * 5);
        let color;
        if (Math.round(Math.random()) === 0)
            color = new THREE.Color('#003d5d');
        else
            //color = new THREE.Color('#f23d5d');
            color = new THREE.Color('#f23d5d');

        let material = new THREE.MeshPhongMaterial({
            color: color
            //side: THREE.DoubleSide
        });

        material.flatShading = true;

        //var material = new THREE.MeshBasicMaterial({
            //color : new THREE.Color(Math.floor(Math.random() * 1) === 1),
            //color : new THREE.Color(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 0),
            //shading: THREE.FlatShading,
        //})

         
       var circle = new THREE.Mesh(circleGeometry, material);
        material.side = THREE.DoubleSide;

        circle.position.x = Math.random() * -distance * 100;
        circle.position.y = Math.random() * -distance * 8;
        circle.position.z = Math.random() * distance * 5;
        circle.rotation.y = Math.random() * 2 * Math.PI;
        circle.scale.x = circle.scale.y = circle.scale.z = Math.random() * 8 + 5;
        dots.add(circle);
    }

    dots.position.x = 14000;
    dots.position.y = 1500;
    dots.position.z = 4000;
    dots.rotation.y = Math.PI * 600;
    dots.rotation.z = Math.PI * 500;

    scene.add(dots);
};
/*


   let circle = new THREE.Mesh(circleGeometry, material);

    let direction = getRandomVector().normalize();
    let minDistance = MAX_DISTANCE * 8;
    let maxDistance = minDistance + 0.5;
    direction.multiplyScalar(Math.random() * (maxDistance - minDistance) + minDistance);

    circle.position.add(direction);

    dots.add(circle);
    }
    scene.add(dots);
} 
*/


function getRandomVector(max_distance) {
    if (max_distance === undefined)
        max_distance = 1;
    return new THREE.Vector3(getRandom(max_distance), getRandom(max_distance), getRandom(max_distance));
}

function getRandom(max_distance) {
    let random = Math.random() * max_distance;
    random *= Math.floor(Math.random() * 2) === 1 ? 1 : -1;
    return random;
}



// -- events -- //
function onMouseMove(event) {
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
     mouseX = event.clientX - window.innerWidth / 2 ;
     mouseY = event.clientY - window.innerHeight / 2 ;
    //camera.position.x += (mouseX - camera.position.x) * 0.01;
    //camera.position.y += (mouseY - camera.position.y) * 0.01;
    // camera.lookAt(scene.position);
};

function onDocumentMouseDown(event) {

    event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);

    var intersects = raycaster.intersectObjects(diamondsGroup.children);
    if (intersects.length > 0) {
        var book = intersects[0].object.userData;
        console.log("click", book);
        //alert("book" + book.title);

        //swal(book.title + book.authors);


        swal(book.title + " \n " + " " + book.authors.map(function(x){return x.author_name}).join(", ") +   " \n" + book.category, {
            buttons: ["return", "open" ],
        }).then (function(button){
            console.log("button", button)
            if (button) {
               window.location = "/books/"+book.id 
            }
            
        });



    }

};

function onDocumentMouseWheel( event ) {

    fov -= event.wheelDeltaY * 0.05;
    camera.projectionMatrix = THREE.Matrix4.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 );

}


function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.updateProjectionMatrix();
    controls.update();
};

// ---- //
function animate() {
    requestAnimationFrame(animate);
    controls.update();
    render();
};

// -- render all -- //
function render() {

    var timer = 0.00001 * Date.now();

    for (var i = 0, l = diamondsGroup.children.length; i < l; i++) {
        var object = diamondsGroup.children[i];
        object.position.y = 500 * Math.cos(timer + i);
        object.rotation.y += Math.PI / 500;
    }

    // update the picking ray with the camera and mouse position
    raycaster.setFromCamera(mouse, camera);

    // calculate objects intersecting the picking ray
    var intersects = raycaster.intersectObjects(diamondsGroup.children);

    if (intersects.length > 0) {
        if (INTERSECTED != intersects[0].object) {
            if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
            INTERSECTED = intersects[0].object;
            INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
            INTERSECTED.material.emissive.setHex(Math.random() * 0xff00000 - 0xff00000);
        }
    } else {
        if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
        INTERSECTED = null;
    }

    renderer.render(scene, camera);
};

// -- run functions -- //
//init();
//animate();

    </script>

</body>
</html>