create-three-bun-ox 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
package/create.js CHANGED
@@ -36,6 +36,7 @@ for (const file of files) {
36
36
  cpSync(join(__dirname, file), join(dest, file));
37
37
  }
38
38
 
39
+ cpSync(join(__dirname, "assets"), join(dest, "assets"), { recursive: true });
39
40
  cpSync(join(__dirname, "src"), join(dest, "src"), { recursive: true });
40
41
 
41
42
  writeFileSync(
@@ -96,4 +97,4 @@ try {
96
97
 
97
98
  console.log(`\nDone! Created ${basename(dest)}`);
98
99
  console.log(`\n cd ${arg}`);
99
- console.log(" bun run dev\n");
100
+ console.log(" bun run dev\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-three-bun-ox",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "description": "A minimal Bun + Three.js template with oxlint and oxfmt.",
5
5
  "homepage": "https://github.com/spinualexandru/create-three-bun-ox#readme",
6
6
  "bugs": {
@@ -12,10 +12,11 @@
12
12
  "type": "git",
13
13
  "url": "git+https://github.com/spinualexandru/create-three-bun-ox.git"
14
14
  },
15
- "bin": "create.js",
15
+ "bin": { "create-three-bun-ox": "create.js" },
16
16
  "files": [
17
17
  "create.js",
18
18
  "README.md",
19
+ "assets",
19
20
  "index.html",
20
21
  "server.ts",
21
22
  "src",
@@ -27,6 +28,7 @@
27
28
  "type": "module",
28
29
  "module": "server.ts",
29
30
  "scripts": {
31
+ "npx": "node ./create.js",
30
32
  "dev": "bun --hot ./server.ts",
31
33
  "start": "bun run dev",
32
34
  "fmt": "oxfmt server.ts index.html src package.json README.md tsconfig.json .oxlintrc.json .oxfmtrc.json",
package/server.ts CHANGED
@@ -4,6 +4,10 @@ const server = Bun.serve({
4
4
  port: Number(Bun.env.PORT ?? 3000),
5
5
  routes: {
6
6
  "/": index,
7
+ "/assets/*": (req) => {
8
+ const url = new URL(req.url);
9
+ return new Response(Bun.file(`.${url.pathname}`));
10
+ },
7
11
  },
8
12
  development: {
9
13
  hmr: true,
package/src/main.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import * as THREE from "three";
2
2
  import { OrbitControls } from "three/addons/controls/OrbitControls.js";
3
+ import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
3
4
 
4
5
  const scene = new THREE.Scene();
5
6
  scene.background = new THREE.Color(0x0f172a);
6
7
 
7
8
  const camera = new THREE.PerspectiveCamera(50, innerWidth / innerHeight, 0.1, 100);
8
- camera.position.set(3, 2, 4);
9
+ camera.position.set(3.8, 2.3, 4.8);
9
10
 
10
11
  const renderer = new THREE.WebGLRenderer({ antialias: true });
11
12
  renderer.setSize(innerWidth, innerHeight);
@@ -16,7 +17,7 @@ document.body.append(renderer.domElement);
16
17
 
17
18
  const controls = new OrbitControls(camera, renderer.domElement);
18
19
  controls.enableDamping = true;
19
- controls.target.set(0, 0.75, 0);
20
+ controls.target.set(0, 1.1, 0);
20
21
  controls.update();
21
22
 
22
23
  const plane = new THREE.Mesh(
@@ -27,25 +28,62 @@ plane.rotation.x = -Math.PI / 2;
27
28
  plane.receiveShadow = true;
28
29
  scene.add(plane);
29
30
 
30
- const sphere = new THREE.Mesh(
31
- new THREE.SphereGeometry(0.75, 32, 16),
32
- new THREE.MeshStandardMaterial({ color: 0xf59e0b, roughness: 0.35, metalness: 0.05 }),
31
+ const logo = new THREE.Group();
32
+ scene.add(logo);
33
+
34
+ const loader = new GLTFLoader();
35
+
36
+ loader.load(
37
+ "/assets/three-logo.glb",
38
+ (gltf) => {
39
+ const model = gltf.scene;
40
+
41
+ model.traverse((child) => {
42
+ if (child instanceof THREE.Mesh) {
43
+ child.castShadow = true;
44
+ child.receiveShadow = true;
45
+ }
46
+ });
47
+
48
+ const box = new THREE.Box3().setFromObject(model);
49
+ const size = box.getSize(new THREE.Vector3());
50
+ const maxDimension = Math.max(size.x, size.y, size.z) || 1;
51
+ const scale = 2.2 / maxDimension;
52
+
53
+ model.scale.setScalar(scale);
54
+ model.updateMatrixWorld(true);
55
+
56
+ const scaledBox = new THREE.Box3().setFromObject(model);
57
+ const scaledSize = scaledBox.getSize(new THREE.Vector3());
58
+ const scaledCenter = scaledBox.getCenter(new THREE.Vector3());
59
+
60
+ model.position.x -= scaledCenter.x;
61
+ model.position.y -= scaledCenter.y;
62
+ model.position.z -= scaledCenter.z;
63
+ model.position.y += scaledSize.y * 0.5 + 0.02;
64
+
65
+ logo.add(model);
66
+ },
67
+ undefined,
68
+ (error) => {
69
+ console.error("Failed to load /assets/three-logo.glb", error);
70
+ },
33
71
  );
34
- sphere.position.y = 0.75;
35
- sphere.castShadow = true;
36
- scene.add(sphere);
37
72
 
38
73
  const light = new THREE.DirectionalLight(0xffffff, 3);
39
- light.position.set(3, 5, 2);
74
+ light.position.set(3.5, 5.5, 3);
40
75
  light.castShadow = true;
41
76
  scene.add(light);
42
77
 
78
+ const fillLight = new THREE.HemisphereLight(0xe2e8f0, 0x0f172a, 1.2);
79
+ scene.add(fillLight);
80
+
43
81
  const panel = document.createElement("div");
44
82
  panel.className = "ui";
45
83
  panel.innerHTML = `
46
84
  <label>
47
- Sphere X
48
- <input id="sphere-x" type="range" min="-3" max="3" step="0.01" value="0" />
85
+ Logo Rotation
86
+ <input id="logo-rotation" type="range" min="-180" max="180" step="1" value="0" />
49
87
  </label>
50
88
  <label>
51
89
  Light Intensity
@@ -54,12 +92,12 @@ panel.innerHTML = `
54
92
  `;
55
93
  document.body.append(panel);
56
94
 
57
- const sphereX = panel.querySelector<HTMLInputElement>("#sphere-x");
95
+ const logoRotation = panel.querySelector<HTMLInputElement>("#logo-rotation");
58
96
  const lightIntensity = panel.querySelector<HTMLInputElement>("#light-intensity");
59
97
 
60
- if (sphereX && lightIntensity) {
61
- sphereX.addEventListener("input", () => {
62
- sphere.position.x = Number(sphereX.value);
98
+ if (logoRotation && lightIntensity) {
99
+ logoRotation.addEventListener("input", () => {
100
+ logo.rotation.y = THREE.MathUtils.degToRad(Number(logoRotation.value));
63
101
  });
64
102
 
65
103
  lightIntensity.addEventListener("input", () => {