I am not able to Get UV Images from the Model map the texture of glb model it is showing only dots.
{% block content %}
{% load static %}
<style>
.web-images {
position: absolute;
}
.web-btn {
position: absolute;
top: 130px;
}
</style>
<div class="web-images" id="loadImageBtn">
<img style="width: 70px; height: 70px;" src="/static/laikailike/images/prints/IMG_0540-_2_.webp" alt="Image 1">
<img style="width: 70px; height: 70px" src="/static/laikailike/images/prints/IMG_0542.webp" alt="Image 2">
<img style="width: 70px; height: 70px;" src="/static/laikailike/images/prints/PRA02683.webp" alt="Image 3">
</div>
<div class="web-btn">
<button id="showUVLayerBtn">Show UV Layer</button>
</div>
<div id="canvas-container"></div>
<canvas id="uvLayer" width="400" height="400"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
<script>
var scene = new THREE.Scene();
var click_object_name = null;
let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff);
document.getElementById('canvas-container').appendChild(renderer.domElement);
var loader = new THREE.GLTFLoader();
loader.setPath("{% static '/laikailike/models/' %}");
var model;
loader.load('bag-08-24-2023-c4d.glb', function (gltf) {
model = gltf.scene;
scene.add(model);
});
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(0, 2, 2);
scene.add(directionalLight);
var ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
camera.position.set(0.0, 0.0, 80);
camera.up.set(0.0, 1.0, 0.0);
camera.lookAt(new THREE.Vector3(0.0, 0.0, 0.0));
const dynamicImages = document.querySelectorAll('#loadImageBtn img');
dynamicImages.forEach((image) => {
image.addEventListener('click', function () {
imageUrl = this.getAttribute('src');
loadImageTexture(imageUrl);
});
});
scene.add(camera);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
controls.enablePan = true;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
renderer.domElement.addEventListener('click', onClick, false);
function onClick(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
click_object_name = intersects[0].object.name;
console.log('Clicked on object:', intersects[0].object.name);
}
}
let horizontalOffset = 0;
let verticalOffset = 0;
let imageUrl = "";
function loadImageTexture(imageUrl) {
if (!model) return;
model.traverse((child) => {
if (child.isMesh && child.name === click_object_name) {
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load(imageUrl);
texture.magFilter = THREE.NearestFilter;
texture.minFilter = THREE.NearestFilter;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
child.material = new THREE.MeshBasicMaterial({
map: texture,
});
child.castShadow = true;
child.receiveShadow = true;
child.material.needsUpdate = true;
// After applying the new texture, render the UV layer.
renderUVLayer();
}
});
}
const uvCanvas = document.getElementById('uvLayer');
const uvCtx = uvCanvas.getContext('2d');
function renderUVLayer() {
if (!model) {
console.error('Model is not loaded.');
return;
}
const uvCanvas = document.getElementById('uvLayer');
const uvCtx = uvCanvas.getContext('2d');
// Clear the canvas
uvCtx.clearRect(0, 0, uvCanvas.width, uvCanvas.height);
// Set a background color (e.g., white)
uvCtx.fillStyle = 'white';
uvCtx.fillRect(0, 0, uvCanvas.width, uvCanvas.height);
// Draw UV grid lines
uvCtx.strokeStyle = 'black';
uvCtx.lineWidth = 1;
const meshObjects = model.children.filter(child => child instanceof THREE.Mesh);
meshObjects.forEach(mesh => {
const uvs = mesh.geometry.attributes.uv.array;
for (let i = 0; i < uvs.length; i += 2) {
// Extract UV coordinates for a single point
const u = uvs[i];
const v = uvs[i + 1];
// Calculate pixel coordinates on the UV canvas
const x = u * uvCanvas.width;
const y = (1 - v) * uvCanvas.height;
// Draw a small dot at the UV coordinates
uvCtx.fillStyle = 'black';
uvCtx.fillRect(x, y, 1, 1);
}
});
}
// Function to sample color from the texture at given UV coordinates
function sampleTextureColor(texture, u, v) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = texture.image.width;
const height = texture.image.height;
canvas.width = width;
canvas.height = height;
ctx.drawImage(texture.image, 0, 0, width, height);
// Calculate pixel coordinates
const x = Math.floor(u * width);
const y = Math.floor((1 - v) * height);
// Get the pixel color at the calculated coordinates
const pixelData = ctx.getImageData(x, y, 1, 1).data;
// Return the color as rgba string
return `rgba(${pixelData[0]}, ${pixelData[1]}, ${pixelData[2]}, 1)`;
}
document.getElementById('showUVLayerBtn').addEventListener('click', function () {
renderUVLayer();
});
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
{% endblock %}