Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerald-Golden authored Apr 1, 2024
1 parent f23bf82 commit 6191f31
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 0 deletions.
37 changes: 37 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>three</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="icon" type="image/x-icon"
href="data:image/png;base64,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">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js"
}
}
</script>
<link rel="stylesheet" href="styles.css">
</head>

<body>
<div id="instructions">
<p>Choose and left click on the canvas to place objects.</p>
<p>Hold Alt and left click on an object to delete it.</p>
<p>Right click on two objects and press "Connect" and continue to right click on othe objects to crate a spline.
</p>
</div>
<canvas id="my_canvas"></canvas>
<div class="objects">
<button class="object" id="box">BOX 🟦</button>
<button class="object" id="sphere">SPHERE 🔴</button>
<button class="object" id="connect">CONNECT 🖍</button>
</div>
<script src="script.js" type="module"></script>
</body>

</html>
236 changes: 236 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.js';
import { TransformControls } from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/TransformControls.js';
import { CatmullRomCurve3 } from 'https://cdn.jsdelivr.net/npm/[email protected]/src/extras/curves/CatmullRomCurve3.js';

let currentMesh, transformControl;

const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
const onUpPosition = new THREE.Vector2();
const onDownPosition = new THREE.Vector2();

let instructionsShown = false;
function showInstructions() {
if (!instructionsShown) {
instructionsShown = true;
const instructions = document.getElementById('instructions');
}
}

showInstructions();

//scene
var scene = new THREE.Scene();

//camera
var camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 250, 1000);

//renderer
var renderer = new THREE.WebGLRenderer({ canvas: my_canvas });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

//controls
var controls = new OrbitControls(camera, renderer.domElement);

//background
scene.background = new THREE.Color(0xf0f0f0);

//light
var light = new THREE.PointLight(0xffffff, 1, 0);
light.position.set(50, 200, 0);
scene.add(light);

//materials
var redMaterial = new THREE.MeshStandardMaterial({ color: 0xFF0000, emissive: 0xFF0000 });
var blueMaterial = new THREE.MeshStandardMaterial({ color: 0x0000FF, emissive: 0x0000FF });

//meshes
var planeGeometry = new THREE.PlaneGeometry(1500, 1500);
var planeMaterial = new THREE.MeshBasicMaterial({ color: 0x808080, side: THREE.DoubleSide });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
plane.position.y = 0;
scene.add(plane);

//crate objects[]
var objects = [];
objects.push(plane);
let createobject = null;
var connects = [];

//choose object

$(".object").click(function () {
if (($(this).attr("id")) === "box") {
createobject = "box";
}
if (($(this).attr("id")) === "sphere") {
createobject = "sphere";
}
if (($(this).attr("id")) === "connect") {
connectObjects();
}
});

//click events
transformControl = new TransformControls(camera, renderer.domElement);
transformControl.showY = false
transformControl.addEventListener('dragging-changed', function (event) {
controls.enabled = !event.value;
});
scene.add(transformControl);

document.addEventListener('mousedown', onPointerDown);
document.addEventListener('mouseup', onPointerUp);
document.addEventListener('contextmenu', onRightClick);
document.addEventListener('dblclick', onPointerClick);
window.addEventListener('resize', onWindowResize);

function onPointerDown(event) {
onDownPosition.x = event.clientX;
onDownPosition.y = event.clientY;
}

function onPointerUp(event) {
onUpPosition.x = event.clientX;
onUpPosition.y = event.clientY;

if (onDownPosition.distanceTo(onUpPosition) === 0) {
transformControl.detach();
render();
}
}
let tubeMesh;
function connectObjects() {
if (connects.length >= 2) {
const points = [];

for (let i = 0; i < connects.length; i++) {
const object = connects[i];
points.push(new THREE.Vector3(object.position.x, object.position.y, object.position.z));
}
const curve = new CatmullRomCurve3(points);
if (tubeMesh) {
scene.remove(tubeMesh);
}
const tubeGeometry = new THREE.TubeGeometry(curve, 1000, 1, 10, false); //(path,tubularSegments , radius,radialSegments , closed )
const tubeMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
tubeMesh = new THREE.Mesh(tubeGeometry, tubeMaterial);
scene.add(tubeMesh);

render();
} else {
scene.remove(tubeMesh);
console.log("At least two objects are required to connect.");
}
}

function onPointerClick(event) {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;

raycaster.setFromCamera(pointer, camera);
let intersects = raycaster.intersectObjects(objects, false);

const intersectionPoint = intersects[0].point;
// console.log('Grid Position:', intersectionPoint);

placeobject(intersects, intersectionPoint);
}

function placeobject(intersects, intersectionPoint) {
if (intersects.length > 1) {
const object = intersects[0].object;
if (transformControl) {
transformControl.attach(object);
// console.log(object);
}
} else {
if (transformControl) {
transformControl.detach();

if (createobject === "sphere") {
var sphereGeometry = new THREE.SphereGeometry(10);
currentMesh = new THREE.Mesh(sphereGeometry, redMaterial);
currentMesh.position.set(intersectionPoint.x, 10, intersectionPoint.z);
scene.add(currentMesh);
objects.push(currentMesh);
} else if (createobject === "box") {
var boxGeometry = new THREE.BoxGeometry(20, 20, 20);
currentMesh = new THREE.Mesh(boxGeometry, blueMaterial);
currentMesh.position.set(intersectionPoint.x, 10, intersectionPoint.z);
scene.add(currentMesh);
objects.push(currentMesh);
}
render();
}
}
}

function onRightClick(event) {
if (event.altKey) {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;

raycaster.setFromCamera(pointer, camera);
let intersects = raycaster.intersectObjects(objects, false);
if (intersects.length > 1) {
const object = intersects[0].object;
scene.remove(object);
objects = objects.filter(item => item !== object);
connects = connects.filter(item => item !== object);
connectObjects();
console.log(intersects);
render();
}
}
else {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;

raycaster.setFromCamera(pointer, camera);
let intersects = raycaster.intersectObjects(objects, false);

// const intersectionPoint = intersects[0].point;

if (intersects.length > 1) {
const object = intersects[0].object;
// console.log(object);
connects.push(object);
// console.log(connects);
}
}
}




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

//Render
function render() {
requestAnimationFrame(render);
if (tubeMesh && connects.length >= 2) {
const points = [];
for (let i = 0; i < connects.length; i++) {
const object = connects[i];
points.push(new THREE.Vector3(object.position.x, object.position.y, object.position.z));
}
const curve = new CatmullRomCurve3(points);
tubeMesh.geometry.dispose();
tubeMesh.geometry = new THREE.TubeGeometry(curve, 100, 1, 10, false);
} else {
scene.remove(tubeMesh);
}
renderer.render(scene, camera);
}

render();
34 changes: 34 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
body {
margin: 0;
overflow: hidden;
}

#my_canvas {
position: absolute;
width: 90%;
height: 100vh;
margin: 0;
padding: 0;
}

.objects {
position: absolute;
top: 10px;
left: 10px;
display: flex;
z-index: 99;
flex-direction: column;
}

.object {
margin-bottom: 5px;
background-color: black;
color: aliceblue;
cursor: pointer;
}

#instructions {
position: absolute;
right: 10px;
z-index: 99;
}

0 comments on commit 6191f31

Please sign in to comment.