Three.js checkers game

I am in very early stages of making a Three.js checkers game. I have the board made, and now i want to put the board on top of a table, how can I do it? Here is my code so far. (the comments are in Portuguese, sorry).

// Cria uma nova cena 3D usando a biblioteca Three.js.
var scene = new THREE.Scene();

// Inicializa uma câmera perspectiva com um campo de visão de 80 graus, uma razão de aspecto baseada na largura e altura da janela do navegador, e define distâncias de recorte entre 0.1 e 1000.
var camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);

// Posiciona a câmera 10 unidades distante do plano xy na direção z.
camera.position.z = 10;

// Cria um renderizador WebGL que permite renderizar a cena 3D no navegador.
var renderer = new THREE.WebGLRenderer();

// Define o tamanho do renderizador para ocupar a largura e altura completas da janela.
renderer.setSize(window.innerWidth, window.innerHeight);

// Define a cor de fundo do renderizador para um tom escuro de verde.
scene.background = new THREE.Color(0x38761D);

// Adiciona o elemento DOM do renderizador ao corpo do documento, permitindo que a cena seja visível no navegador.
document.body.appendChild(renderer.domElement);

// Instancia um objeto Board (presumivelmente uma classe definida em outro lugar no código) que gerencia o tabuleiro do jogo.
var board = new Board();

// Chama o método build da instância board, passando a cena como parâmetro para adicionar elementos ao tabuleiro na cena.
board.build(scene);

// Calcula o campo de visão vertical em radianos a partir do campo de visão em graus da câmera.
var vFOV = camera.fov * Math.PI / 180;

// Calcula a altura visível com base na distância da câmera (10 unidades).
var height = 2 * Math.tan(vFOV / 2) * 10;

// Calcula a razão de aspecto da janela.
var aspect = window.innerWidth / window.innerHeight;

// Calcula a largura visível com base na altura visível e na razão de aspecto.
var width = height * aspect;


// Adiciona uma luz ambiente à cena para iluminar todos os objetos igualmente com uma cor cinza escura.
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

// Adiciona uma luz focal à cena, posiciona-a acima da origem e permite que ela projete sombras.
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(0, 0, 10);
spotLight.castShadow = true;
scene.add(spotLight);

var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 0, 10);
pointLight.castShadow = true;




var lightType = 'ambient';  // Variável para controlar qual luz está ativa

// Cria uma div para mostrar o tipo de luz ativa
var lightIndicator = document.createElement('div');
lightIndicator.style.position = 'absolute';
lightIndicator.style.top = '50px';
lightIndicator.style.right = '10px';
lightIndicator.innerHTML = "Luz Ativa: Ambient Light";
document.body.appendChild(lightIndicator);

// Função para alternar entre as luzes
function toggleLight() {
    if (lightType === 'ambient') {
        scene.remove(ambientLight);
        scene.add(pointLight);
        lightType = 'point';
        lightIndicator.innerHTML = "Luz Ativa: Point Light";
    } else {
        scene.remove(pointLight);
        scene.add(ambientLight);
        lightType = 'ambient';
        lightIndicator.innerHTML = "Luz Ativa: Ambient Light";
    }
}

// Cria um botão na interface para alternar as luzes
var button = document.createElement('button');
button.innerHTML = "Alterar Iluminação";
button.onclick = toggleLight;
button.style.position = 'absolute';
button.style.top = '10px';
button.style.right = '10px';
button.style.fontSize = '20px';
button.style.border = "thick solid #359bbd";
button.style.backgroundColor = "#2a35c9";
button.style.color = "#ffffff"; // Define a cor da fonte para branco
document.body.appendChild(button);


// Cria um raio para detectar interseções com objetos na cena com base nas coordenadas do mouse.
var raycaster = new THREE.Raycaster();

// Inicializa um objeto para armazenar as coordenadas x e y do mouse.
var mouse = { x: 0, y: 0 };

// Cria e configura uma div para exibir informações sobre as peças no jogo, estilizando-a e adicionando-a ao corpo do documento.
var black = document.createElement('div');
black.setAttribute('id', 'black');
black.style.position = 'absolute';
black.style.color = '#D1D1D1';
black.style.width = 100;
black.style.height = 100;
black.style.fontSize = '24px';
black.innerHTML = "<table>" +
    "<tr style='font-weight:bold;'><td>Brancas</td><td>( 12 Restantes )</td></tr>" +
    "<tr style='color: black'><td>Vermelhas</td><td>( 12 Restantes )</td></tr>" +
    "</table>";
black.style.border = "thick solid #359bbd";
black.style.backgroundColor = "#2a35c9";
black.style.top = 1.5 + '%';
black.style.left = 1 + '%';
black.style.padding = "1%";
document.body.appendChild(black);

// Define uma variável para controlar se uma peça está sendo movida.
var grabbed = false;

// Inicializa os controles de órbita para permitir a interação com a câmera através do mouse.
controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);

// Configura eventos do mouse para manipulação das peças do jogo e interação com a cena.
$(document).ready(function () {
    $(document.body).mousedown(function(event) {
        // Atualiza a posição do mouse com base no evento do clique.
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        // Define o raio a partir da posição da câmera e das coordenadas do mouse.
        raycaster.setFromCamera(mouse, camera);

        // Calcula interseções com objetos na cena.
        var intersects = raycaster.intersectObjects(scene.children);

        // Processa interseções para manipulação de peças ou controle da câmera.
        for (var i = 0; i < intersects.length; i++) {
            if (intersects[i].object['checkersObject'] == 'Piece') {
                var success = board.grab(intersects[i].object["col"], intersects[i].object["row"]);
                if (success) {
                    board.showLegals(intersects[i].object["col"], intersects[i].object["row"], scene);
                    grabbed = true;
                }
            } else if (intersects[i].object['checkersObject'] == 'Tile') {
                controls.enabled = false;
            }
        }

        // Atualiza a posição da peça sendo segurada com base na posição do mouse.
        board.moveHolding(scene, camera, mouse.x, mouse.y);
    });

    $(document.body).mousemove(function(event) {
        // Atualiza continuamente a posição do mouse durante o movimento.
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        // Move a peça que está sendo segurada conforme o mouse se move.
        board.moveHolding(scene, camera, mouse.x, mouse.y);
    });

    $(document.body).mouseup(function (event) {
        // Atualiza a posição do mouse quando o botão do mouse é solto.
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        // Define o raio a partir da posição da câmera e das coordenadas do mouse.
        raycaster.setFromCamera(mouse, camera);

        // Calcula interseções com objetos na cena.
        var intersects = raycaster.intersectObjects(scene.children);

        // Processa interseções para soltar peças ou reativar controles de câmera.
        for (var i = 0; i < intersects.length; i++) {
            if (intersects[i].object['checkersObject'] == 'Tile') {
                var success = board.drop(intersects[i].object["col"], intersects[i].object["row"], scene);
                if (success) {
                    grabbed = false;
                }
            }
            board.unshowLegals(scene);
        }
        controls.enabled = true;
    });

    // Chama a função de renderização para atualizar a visualização da cena.
    render();
});

// Configura o evento de redimensionamento da janela para ajustar a câmera e o renderizador.
$(window).resize(function() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

// Define a posição original da câmera e controla se a animação está ativa.
var origin = camera.position;
var animate = true;
var clock = new THREE.Clock();

// Função para animar a câmera se necessário (não utilizada ativamente).
function rotateAnimation() {
    camera.position.y += clock.getElapsedTime() * 2.5;
    camera.position.z += clock.getElapsedTime() * 2.5;
}

function createTable(scene) {
    const tableWidth = 200; // Mais largo que o tabuleiro para dar uma boa aparência
    const tableHeight = 5;  // Altura razoável para a mesa
    const tableDepth = 100; // Profundidade proporcional à largura

    const tableGeometry = new THREE.BoxGeometry(tableWidth, tableHeight, tableDepth);
    const tableMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 }); // Cor de madeira
    const tableMesh = new THREE.Mesh(tableGeometry, tableMaterial);
    tableMesh.position.set(0, -tableHeight / 2, 0); // Ajuste para alinhar ao centro na base
    scene.add(tableMesh);

    return tableMesh.position.y + tableHeight / 2; // Retorna a posição do topo da mesa
}

function setupScene() {
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x87CEEB); // Azul claro como céu

    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 50, 150);
    camera.lookAt(new THREE.Vector3(0, 0, 0));

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    const ambientLight = new THREE.AmbientLight(0x404040);
    scene.add(ambientLight);

    const pointLight = new THREE.PointLight(0xffffff, 1, 100);
    pointLight.position.set(50, 50, 50);
    scene.add(pointLight);

    const tableTopHeight = createTable(scene);

    const board = new Board();
    board.build(scene);
    board.mesh.position.y = tableTopHeight; // Posiciona o tabuleiro em cima da mesa

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

    animate();
}

setupScene();


// Função de renderização que é chamada recursivamente para atualizar e renderizar a cena.
function render() {
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}

You can use:

let bounds = new THREE.Box3().setFromObject( scene )

To get the bounds of an object in the world…

so for instance you could get the bounds.min.y of the board, and the bounds.max.y of the table and position the board by subtracting the 2 and adding to board.position.y…