// import * as THREE from "three";
var rawHTML = `
<style>
#promptInput, #sendPrompt, #inputArea {
display: none;
}
#apiKey, #inputArea {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 100; /* Ensures it's above other elements */
background: #a2a2a2a2;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
#apiInput, #promptInput {
width: 300px;
height: 30px;
font-size: 20px;
padding: 5px;
border-radius: 5px;
border: 1px solid #000;
}
#promptInput {
width: 600px;
height: 30px;
font-size: 20px;
padding: 5px;
border-radius: 5px;
border: 1px solid #000;
}
#setApi {
width: 100px;
height: 40px;
font-size: 20px;
border-radius: 5px;
padding: 5px;
border: 1px solid #000;
cursor: pointer;
}
</style>
<div id="inputArea">
<input type="text" id="promptInput" placeholder="Enter image prompt" />
<button id="sendPrompt">Generate Image</button>
</div>
<div id="apiKey">
<input type="text" id="apiInput" placeholder="Enter Api Key" />
<button id="setApi">Set Key</button>
</div>`;
document.body.innerHTML += rawHTML;
// Prompt input setup
const apiKeyInput = document.getElementById("apiKey");
const apiInput = document.getElementById("apiInput");
const setApiButton = document.getElementById("setApi");
// Event listener for the set API key button
setApiButton.addEventListener("click", function () {
if (apiInput.value == "") return; // no empty API keys
apikey = apiInput.value;
apiKeySet = true;
apiKeyInput.style.display = "none"; // Hide the prompt input
viewInput.style.display = "none";
getMusic();
});
// Basic setup
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// skybox setup
var loader = new THREE.CubeTextureLoader();
var texture = loader.load([
"uploads/yammers/DaylightRight.png",
"uploads/yammers/DaylightLeft.png",
"uploads/yammers/DaylightTop.png",
"uploads/yammers/DaylightBottom.png",
"uploads/yammers/DaylightFront.png",
"uploads/yammers/DaylightBack.png",
]);
scene.background = texture;
// Lighting setup
var ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
var directionalLight2 = new THREE.DirectionalLight(0xffffff, 1);
directionalLight2.position.set(-1, -1, -1).normalize();
scene.add(directionalLight2);
// Floor setup
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floorMaterial = new THREE.MeshLambertMaterial({ color: 0x808080 });
// For a custom textured
var textureLoader = new THREE.TextureLoader();
var floorTexture = textureLoader.load("uploads/yammers/floor-Copy.jpg"); // Replace with path to texture
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set(50, 50);
var floorMaterial = new THREE.MeshLambertMaterial({ map: floorTexture });
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -Math.PI / 2;
floor.position.y = -0.5;
scene.add(floor);
function createGalleryWall(width, height, depth, position, texturePath) {
var geometry = new THREE.BoxGeometry(width, height, depth);
var textureLoader = new THREE.TextureLoader();
var wallTexture = textureLoader.load(texturePath);
wallTexture.wrapS = wallTexture.wrapT = THREE.RepeatWrapping;
wallTexture.repeat.set(1, 1);
var material = new THREE.MeshLambertMaterial({ map: wallTexture });
var wall = new THREE.Mesh(geometry, material);
wall.position.set(position.x, position.y, position.z);
scene.add(wall);
return wall;
}
var wall1 = createGalleryWall(
200,
70,
20,
{ x: 0, y: 20, z: -100 },
"uploads/yammers/artWall.jpg"
);
var wall2a = createGalleryWall(
85,
70,
20,
{ x: 60, y: 20, z: 100 },
"uploads/yammers/artWall.jpg"
);
var wall2b = createGalleryWall(
85,
70,
20,
{ x: -60, y: 20, z: 100 },
"uploads/yammers/artWall.jpg"
);
var wall3 = createGalleryWall(
20,
70,
200,
{ x: -100, y: 20, z: 0 },
"uploads/yammers/artWall.jpg"
);
var wall4 = createGalleryWall(
20,
70,
200,
{ x: 100, y: 20, z: 0 },
"uploads/yammers/artWall.jpg"
);
// Wall setup for the generated image
var allFrames = [];
var frameConfigs = [
{ position: { x: -40, y: 27.5, z: -89 }, rotationY: 0 },
{ position: { x: 40, y: 27.5, z: -89 }, rotationY: 0 },
{ position: { x: 89, y: 27.5, z: -40 }, rotationY: -Math.PI / 2 },
{ position: { x: -89, y: 27.5, z: 40 }, rotationY: Math.PI / 2 },
{ position: { x: -89, y: 27.5, z: -40 }, rotationY: -Math.PI / 2 },
{ position: { x: 89, y: 27.5, z: 40 }, rotationY: Math.PI / 2 },
{ position: { x: -52.5, y: 27.5, z: 89 }, rotationY: 0 },
{ position: { x: 52.5, y: 27.5, z: 89 }, rotationY: 0 },
];
// create the frames
frameConfigs.forEach((config, index) => {
// Create a new material for each wall
var frameMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
map: textureLoader.load("uploads/yammers/frame.jpg"), // Load the default texture
});
var frameGeometry = new THREE.PlaneGeometry(50, 50);
var frame = new THREE.Mesh(frameGeometry, frameMaterial);
// Set position and rotation
frame.position.set(config.position.x, config.position.y, config.position.z);
frame.rotation.y = config.rotationY;
// Add border
addBorderToFrame(frame, 0.5, 0x000000);
// Add to the scene
scene.add(frame);
allFrames.push(frame);
});
// adds a frame to the frames
function addBorderToFrame(frame, thickness, color) {
const frameWidth = frame.geometry.parameters.width;
const frameHeight = frame.geometry.parameters.height;
const borderMaterial = new THREE.MeshLambertMaterial({ color: color });
// Top border
const topBorderGeometry = new THREE.BoxGeometry(
frameWidth,
thickness,
thickness
);
const topBorder = new THREE.Mesh(topBorderGeometry, borderMaterial);
topBorder.position.y = frameHeight / 2;
frame.add(topBorder);
// Bottom border
const bottomBorder = new THREE.Mesh(topBorderGeometry, borderMaterial);
bottomBorder.position.y = -frameHeight / 2;
frame.add(bottomBorder);
// Left border
const sideBorderGeometry = new THREE.BoxGeometry(
thickness,
frameHeight + thickness * 2,
thickness
);
const leftBorder = new THREE.Mesh(sideBorderGeometry, borderMaterial);
leftBorder.position.x = -frameWidth / 2;
frame.add(leftBorder);
// Right border
const rightBorder = new THREE.Mesh(sideBorderGeometry, borderMaterial);
rightBorder.position.x = frameWidth / 2;
frame.add(rightBorder);
}
var stand = createGalleryWall(2, 10, 2, { x: 0, y: 5, z: -25 }, "uploads/yammers/artWall.jpg");
// Add a border to the stand
scene.add(stand);
// Button setup for the prompt input
var buttonGeometry = new THREE.BoxGeometry(2, 2, 2);
var buttonMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 });
var button = new THREE.Mesh(buttonGeometry, buttonMaterial);
button.rotation.y = Math.PI / 2;
button.position.set(0, 11, -25);
scene.add(button);
// Raycaster for interaction with the button
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var isPointerLocked = false;
// Mouse click event listener for interaction with the button
function onMouseClick(event) {
document.exitPointerLock(); // Exit pointer lock when text box is focused
isPointerLocked = false;
// Convert mouse position to normalized device coordinates (-1 to +1) for both components
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Update the raycaster
raycaster.setFromCamera(mouse, camera);
// Check if the ray intersects with the button
var intersects = raycaster.intersectObject(button);
if (intersects.length > 0) {
togglePromptInput(); // Toggle the visibility of the prompt input
}
}
function showPromptInput() {
promptInput.style.display = "block"; // Show the prompt input
promptInput.focus(); // Focus on the input
}
// Function to toggle the visibility of the prompt input for image generation
function togglePromptInput() {
if (promptInput.style.display === "block") {
promptInput.style.display = "none"; // Hide the prompt input
viewInput.style.display = "none";
} else {
promptInput.style.display = "block"; // Show the prompt input
viewInput.style.display = "block";
promptInput.focus(); // Focus on the input if it's being shown
}
}
document.addEventListener("click", onMouseClick, false); // Add the mouse click event listener to the document
// Pointer Lock Controls setup
camera.rotation.set(0, 0, 0);
var pitchObject = new THREE.Object3D();
pitchObject.add(camera);
var yawObject = new THREE.Object3D();
yawObject.position.y = 10;
yawObject.add(pitchObject);
var velocity = new THREE.Vector3();
var canJump = false; // A flag to check if the character can jump
var jumpHeight = 7.5; // Adjust as needed
scene.add(yawObject);
const PI_2 = Math.PI / 2; // Constant for the pitch object
// This requests pointer lock when the user clicks on the page
document.addEventListener(
"click",
function () {
if (apiKeySet == false) {
return; // Don't allow movement when the API key hasn't been set
}
document.body.requestPointerLock();
},
false
);
// Mouse movement event listeners
document.addEventListener("mousemove", onMouseMove, false);
var isPointerLocked = false;
// Function to handle mouse movement when pointer lock is enabled
function onMouseMove(event) {
if (!isPointerLocked) return;
var movementX =
event.movementX || event.mozMovementX || event.webkitMovementX || 0;
var movementY =
event.movementY || event.mozMovementY || event.webkitMovementY || 0;
yawObject.rotation.y -= movementX * 0.002;
pitchObject.rotation.x -= movementY * 0.002;
pitchObject.rotation.x = Math.max(
-PI_2,
Math.min(PI_2, pitchObject.rotation.x)
);
}
document.addEventListener("pointerlockchange", lockChange, false);
document.addEventListener("mozpointerlockchange", lockChange, false);
document.addEventListener("webkitpointerlockchange", lockChange, false);
// Function to handle pointer lock change
function lockChange() {
isPointerLocked = document.pointerLockElement === document.body;
}
// Movement variables
var moveForward = false;
var moveBackward = false;
var moveLeft = false;
var moveRight = false;
// Key event listeners
document.addEventListener("keydown", onKeyDown, false);
document.addEventListener("keyup", onKeyUp, false);
// Function to handle key down events
function onKeyDown(event) {
if (isPointerLocked == false) return;
if (promptInput.style.display === "block") return; // Don't allow movement when the prompt input is visible
console.log(event.key);
switch (event.keyCode) {
case 87: // W
moveForward = true;
break;
case 65: // A
moveLeft = true;
break;
case 83: // S
moveBackward = true;
break;
case 68: // D
moveRight = true;
break;
case 32: // Spacebar
console.log("Jumping");
if (canJump === true) velocity.y += jumpHeight;
canJump = false;
break;
}
}
// Function to handle key up events
function onKeyUp(event) {
console.log(event.key);
switch (event.keyCode) {
case 87: // W
moveForward = false;
break;
case 65: // A
moveLeft = false;
break;
case 83: // S
moveBackward = false;
break;
case 68: // D
moveRight = false;
break;
}
}
// OpenAI API setup
const openaiURL = "https://api.openai.com/v1/images/generations"; // URL for DALL-E 3
const themodel = "dall-e-3"; // The OpenAI model for DALL-E 3
var apikey = "";
var apiKeySet = false; // Flag to check if the API key has been set
var theprompt = "";
//
function sendImageRequest() {
var thedata = {
model: themodel,
prompt: theprompt,
n: 1,
size: "1024x1024",
};
var thedatastring = JSON.stringify(thedata);
var proxiedUrl =
"https://corsproxy.io/?" +
encodeURIComponent("https://api.openai.com/v1/images/generations");
fetch(proxiedUrl, {
method: "POST",
headers: {
// Your headers here
"Content-Type": "application/json",
Authorization: "Bearer " + apikey,
},
body: JSON.stringify({
model: themodel,
prompt: theprompt,
n: 1,
size: "1024x1024",
}),
})
.then((response) => response.json())
.then((data) => successfn(data))
.catch((error) => console.error("Error:", error));
}
// function for the replicate api
async function getImage() {
const proxiedUrl =
"https://corsproxy.io/?" +
encodeURIComponent("https://api.replicate.com/v1/predictions");
const token = apikey;
const model =
"39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b";
const prompt = theprompt;
try {
const response = await fetch(proxiedUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Token " + token,
},
body: JSON.stringify({
version: model,
input: { prompt: prompt },
}),
});
const data = await response.json();
console.log(data);
if (data.urls && data.urls.get) {
const pollingUrl =
"https://corsproxy.io/?" + encodeURIComponent(data.urls.get);
await pollForOutput(pollingUrl, token);
}
} catch (error) {
console.error("Error:", error);
}
}
async function pollForOutput(url, token) {
let hasOutput = false;
const maxPollAttempts = 10;
let pollAttempts = 0;
while (!hasOutput && pollAttempts < maxPollAttempts) {
try {
const pollResponse = await fetch(url, {
headers: {
"Content-Type": "application/json",
Authorization: "Token " + token,
},
});
const pollData = await pollResponse.json();
console.log(pollData);
if (pollData.output) {
hasOutput = true;
successfn(pollData.output[0]);
} else {
// Wait for 5 seconds before the next poll
await new Promise((resolve) => setTimeout(resolve, 5000));
}
} catch (error) {
console.error("Error while polling:", error);
break;
}
}
}
async function getMusic() {
const proxiedUrl =
"https://corsproxy.io/?" +
encodeURIComponent("https://api.replicate.com/v1/predictions");
const token = apikey;
const model =
"8cf61ea6c56afd61d8f5b9ffd14d7c216c0a93844ce2d82ac1c9ecc9c7f24e05";
const prompt = "Jazzy art gallery";
try {
const response = await fetch(proxiedUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Token " + token,
},
body: JSON.stringify({
version: model,
input: { prompt: prompt },
}),
});
const data = await response.json();
console.log(data);
if (data.urls && data.urls.get) {
const pollingUrl =
"https://corsproxy.io/?" + encodeURIComponent(data.urls.get);
await pollForMusic(pollingUrl, token);
}
} catch (error) {
console.error("Error:", error);
}
}
async function pollForMusic(url, token) {
let hasOutput = false;
const maxPollAttempts = 10;
let pollAttempts = 0;
while (!hasOutput && pollAttempts < maxPollAttempts) {
try {
const pollResponse = await fetch(url, {
headers: {
"Content-Type": "application/json",
Authorization: "Token " + token,
},
});
const pollData = await pollResponse.json();
console.log(pollData);
if (pollData.output) {
hasOutput = true;
console.log(pollData.output);
var audio = new Audio(pollData.output["audio"]);
audio.loop = true;
audio.play();
} else {
// Wait for 5 seconds before the next poll
await new Promise((resolve) => setTimeout(resolve, 5000));
}
} catch (error) {
console.error("Error while polling:", error);
break;
}
}
}
// Prompt input setup
const promptInput = document.getElementById("promptInput");
const sendPromptButton = document.getElementById("sendPrompt");
const viewInput = document.getElementById("inputArea");
promptInput.addEventListener("focus", function () {
document.exitPointerLock(); // Exit pointer lock when text box is focused
isPointerLocked = false; // Update your pointer lock flag
});
sendPromptButton.addEventListener("click", function () {
sendImageRequest(promptInput.value); // Call your function to send the image request
});
promptInput.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
// sendImageRequest(promptInput.value);
getImage();
// request pointer lock
document.body.requestPointerLock();
// stop input going to the input box
event.preventDefault();
isPointerLocked = true;
promptInput.style.display = "none"; // Hide the prompt input
viewInput.style.display = "none";
}
});
promptInput.addEventListener("input", function () {
theprompt = this.value;
});
function successfn(data) {
console.log(data);
if (allFrames.length === 0) {
// Reset or handle the case where all FrameallFrames have been used
}
var imageUrl = "https://corsproxy.io/?" + encodeURIComponent(data); // Retrieving the URL of the generated image
// Randomly pick a wall
var randomIndex = Math.floor(Math.random() * allFrames.length);
var selectedWall = allFrames[randomIndex];
// Apply texture to the selected wall only
textureLoader.load(imageUrl, function (texture) {
selectedWall.material.map = texture;
selectedWall.material.needsUpdate = true;
});
// Optionally remove the selected wall from the array
allFrames.splice(randomIndex, 1);
}
function errorfn() {
if (apikey == "") {
console.log("Please enter your API key.");
}
console.log("Error");
}
function animate() {
requestAnimationFrame(animate);
if (isPointerLocked) {
velocity.y -= 9.8 * 0.025;
// Apply the velocity
yawObject.translateX(velocity.x);
yawObject.translateY(velocity.y);
yawObject.translateZ(velocity.z);
// Collision detection with the floor
if (yawObject.position.y < 10) {
velocity.y = 0;
yawObject.position.y = 10;
canJump = true;
}
var moveSpeed = 25;
var delta = 0.016; // 60 FPS?
// Movement
var direction = new THREE.Vector3();
direction.z = Number(moveForward) - Number(moveBackward);
direction.x = Number(moveRight) - Number(moveLeft);
direction.normalize();
if (moveForward) yawObject.translateZ(-moveSpeed * delta);
if (moveBackward) yawObject.translateZ(moveSpeed * delta);
if (moveLeft) yawObject.translateX(-moveSpeed * delta);
if (moveRight) yawObject.translateX(moveSpeed * delta);
}
renderer.render(scene, camera);
}
animate();