◆ Portail Antalaha

Annuaire › Code ouvert

Maison 3D pour une agence immobilière

tutorial · Voir le site ↗
Connectez-vous pour copier ce site

Code publié par son auteur, en lecture seule. « Copier dans mon espace » crée un nouveau site à vous (non publié) que vous pouvez modifier librement.

js/outils.js · 6.5 Ko

/* ==========================================================================
 * js/outils.js — PETITES FONCTIONS UTILITAIRES
 * --------------------------------------------------------------------------
 * Ces fonctions n'ont rien de « 3D » : elles servent aux autres fichiers.
 *   - nuancer()         : éclaircir ou assombrir une couleur hexadécimale ;
 *   - generateurAleatoire() : un hasard REPRODUCTIBLE (même graine = mêmes valeurs) ;
 *   - fixerOrdreSol()   : forcer une forme à être dessinée en premier ;
 *   - peindreBoite()    : colorer les 6 faces d'une boîte avec de la lumière simulée ;
 *   - creerFenetre()    : fabrique une fenêtre complète (cadre, vitre, volets).
 * Dépend de : Zdog, Maison.COULEURS (config.js).
 * ========================================================================== */

(function () {
  'use strict';

  /**
   * Éclaircit (facteur > 0) ou assombrit (facteur < 0) une couleur '#rrggbb'.
   * Principe : on mélange la couleur avec du blanc (éclaircir) ou du noir (assombrir).
   *
   * @param {string} hex     Couleur de départ, par exemple '#f2d27a'.
   * @param {number} facteur Entre -1 (noir) et +1 (blanc). 0 = inchangé.
   * @returns {string} La nouvelle couleur au format '#rrggbb'.
   */
  function nuancer(hex, facteur) {
    // '#f2d27a' -> trois nombres de 0 à 255 (rouge, vert, bleu)
    var n = parseInt(hex.slice(1), 16);
    var canaux = [(n >> 16) & 255, (n >> 8) & 255, n & 255];
    var cible = facteur >= 0 ? 255 : 0;          // blanc ou noir
    var force = Math.abs(facteur);
    var texte = '#';
    for (var i = 0; i < 3; i++) {
      var v = Math.round(canaux[i] + (cible - canaux[i]) * force);
      texte += (v < 16 ? '0' : '') + v.toString(16);   // toujours 2 chiffres hexa
    }
    return texte;
  }

  /**
   * Générateur de nombres pseudo-aléatoires reproductible (algorithme « mulberry32 »).
   * Math.random() donnerait un arbre différent à chaque chargement ; ici, avec
   * la même graine, on obtient TOUJOURS le même arbre.
   *
   * @param {number} graine Un entier de départ.
   * @returns {function(): number} Fonction qui renvoie un nombre entre 0 et 1.
   */
  function generateurAleatoire(graine) {
    var a = graine >>> 0;
    return function () {
      a = (a + 0x6D2B79F5) >>> 0;
      var t = a;
      t = Math.imul(t ^ (t >>> 15), t | 1);
      t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
      return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
    };
  }

  /**
   * Force une forme à être dessinée AVANT toutes les autres (comme un sol).
   *
   * Pourquoi ? Zdog dessine les formes de la plus lointaine à la plus proche,
   * en comparant le « z » du CENTRE de chaque forme. Un très grand sol plat
   * a son centre au milieu de la scène : les objets situés derrière lui
   * seraient donc cachés à tort ! On triche en remplaçant la méthode
   * updateSortValue de CETTE forme par une valeur très basse.
   *
   * @param {Zdog.Shape} forme La forme à placer au fond.
   * @param {number} rang      0 = tout au fond, 1 = juste au-dessus, etc.
   */
  function fixerOrdreSol(forme, rang) {
    forme.updateSortValue = function () {
      this.sortValue = -1000000 + rang;
    };
  }

  /**
   * Colore les faces d'une Zdog.Box en simulant un éclairage venant du haut
   * et de la droite : le dessus est plus clair, l'arrière plus sombre.
   * (Affecter box.frontFace = '#xxxxxx' met à jour la couleur de la face.)
   *
   * @param {Zdog.Box} boite    La boîte à peindre.
   * @param {string}   couleur  Couleur de base du mur.
   */
  function peindreBoite(boite, couleur) {
    boite.frontFace = couleur;
    boite.rearFace = nuancer(couleur, -0.22);
    boite.leftFace = nuancer(couleur, -0.14);
    boite.rightFace = nuancer(couleur, -0.06);
    boite.topFace = nuancer(couleur, 0.25);
    boite.bottomFace = nuancer(couleur, -0.3);
  }

  /**
   * Fabrique une fenêtre : cadre + vitre + croisillons (+ volets en option).
   *
   * On utilise un Group (et pas un simple Anchor) : un Group dessine ses
   * enfants DANS L'ORDRE où on les a ajoutés. Ainsi la vitre est toujours
   * dessinée par-dessus le cadre, quel que soit l'angle de vue.
   *
   * @param {Zdog.Anchor} parent  Où accrocher la fenêtre.
   * @param {Object} o  Options : x, y, z (position), rotY (orientation, en radians :
   *                    0 = vers l'avant, TAU/4 = vers la droite, -TAU/4 = vers la gauche,
   *                    TAU/2 = vers l'arrière), largeur, hauteur, volets (booléen).
   * @returns {Zdog.Group} Le groupe de la fenêtre.
   */
  function creerFenetre(parent, o) {
    var C = Maison.COULEURS;
    var l = o.largeur || 14;
    var h = o.hauteur || 18;

    // Le groupe est placé sur le mur, tourné face à l'extérieur.
    var g = new Zdog.Group({
      addTo: parent,
      translate: { x: o.x, y: o.y, z: o.z },
      rotate: { y: o.rotY || 0 },
    });

    // 1) Le cadre en bois : un rectangle plein, un peu plus grand que la vitre.
    //    backface: false => invisible quand on le regarde « par derrière ».
    new Zdog.Rect({
      addTo: g, width: l + 4, height: h + 4, stroke: 1, fill: true,
      color: C.boisFonce, backface: false,
    });

    // 2) La vitre, très légèrement devant le cadre (z = 0,4).
    new Zdog.Rect({
      addTo: g, width: l, height: h, stroke: 1, fill: true,
      color: C.vitre, translate: { z: 0.4 }, backface: false,
    });

    // 3) Les croisillons : deux traits fins, vertical puis horizontal.
    new Zdog.Shape({
      addTo: g, path: [{ y: -h / 2 }, { y: h / 2 }], closed: false,
      stroke: 1.2, color: C.boisFonce, translate: { z: 0.8 }, backface: false,
    });
    new Zdog.Shape({
      addTo: g, path: [{ x: -l / 2 }, { x: l / 2 }], closed: false,
      stroke: 1.2, color: C.boisFonce, translate: { z: 0.8 }, backface: false,
    });

    // 4) Les volets : deux petits rectangles de chaque côté (facultatif).
    if (o.volets) {
      var decalage = l / 2 + 2 + 3.5;        // moitié de la fenêtre + cadre + moitié du volet
      [-1, 1].forEach(function (cote) {      // -1 = gauche, +1 = droite
        new Zdog.Rect({
          addTo: g, width: 7, height: h + 4, stroke: 1, fill: true,
          color: C.volets, translate: { x: cote * decalage, z: 0.4 }, backface: false,
        });
      });
    }
    return g;
  }

  // On expose les fonctions dans l'espace de noms Maison.
  Maison.nuancer = nuancer;
  Maison.generateurAleatoire = generateurAleatoire;
  Maison.fixerOrdreSol = fixerOrdreSol;
  Maison.peindreBoite = peindreBoite;
  Maison.creerFenetre = creerFenetre;
})();