Building 3D Data Center Micro-Modules with Three.js

Building on the previous article covering standard data center construction, this guide walks through implementing 3D micro-modules for data center visualization using Three.js.

1. Component Creation

Assemble the data center from small components, working from the inside out.

1.1 Server Model

Define server geometry and textures via JSON parameters for full attribute control.

var serverConfig = {
  "show": true,
  "uuid": "",
  "name": "equipment_card_2_4",
  "objType": "cube",
  "length": 60,
  "width": 65,
  "height": 20,
  "x": 0,
  "y": 300,
  "z": 0,
  "style": {
    "skinColor": 9593611,
    "skin": {
      "skin_up": { "skinColor": 9593611, "imgurl": "../../img/3dImg/rack_inside.jpg" },
      "skin_down": { "skinColor": 9593611, "imgurl": "../../img/3dImg/rack_inside.jpg" },
      "skin_fore": { "skinColor": 9593611, "imgurl": "../../img/3dImg/rack_inside.jpg" },
      "skin_behind": { "skinColor": 9593611, "imgurl": "../../img/3dImg/server2.jpg" },
      "skin_left": { "skinColor": 9593611, "imgurl": "../../img/3dImg/rack_inside.jpg" },
      "skin_right": { "skinColor": 9593611, "imgurl": "../../img/3dImg/rack_inside.jpg" }
    }
  },
  "showSortNub": 4
};
var serverModel = WT.commonFunc.createServer(serverConfig);

1.2 Server Ports

Retrieve port data via API and generate corresponding geometry.

var portParams = webApi.getPortsFromServerByServerid(serverId);
WT.commonFunc.createPorts(portParams);

2.1 Cabinet Model

The cabinet consists of multiple movable parts, each controllable individually.

{
  show: true,
  name: 'cabinet3',
  actionSign: "cabinet1",
  shellname: 'cabinet3_emptyCabinetshell',
  uuid: '',
  objType: 'emptyCabinet2',
  transparent: true,
  size: { length: 66, width: 70, height: 200, thick: 2 },
  position: { x: 0, y: 305, z: 0 },
  doors: {
    doorType: 'lr',
    doorSize: [1],
    doorname: ['cabinet3_emptyCabinetdoor_01'],
    skins: [{
      skinColor: 0x333333,
      skin_fore: { imgurl: "../../img/3dImg/rack_door_back.jpg" },
      skin_behind: { imgurl: "../../img/3dImg/rack_front_door.jpg" }
    }]
  },
  style: {
    skinColor: 0xff0000,
    skin: {
      skinColor: 0xff0000,
      skin_up: { imgurl: "../../img/3dImg/rack_door_back.jpg" },
      skin_down: { imgurl: "../../img/3dImg/rack_door_back.jpg" },
      skin_fore: { skinColor: 0xff0000, imgurl: "../../img/3dImg/rack1.png" },
      skin_behind: { skinColor: 0xff0000, imgurl: "../../img/3dImg/rack2.png" },
      skin_left: { imgurl: "../../img/3dImg/rack_door_back.jpg" },
      skin_right: { imgurl: "../../img/3dImg/rack_door_back.jpg" }
    }
  }
}

2.2 Virtual Frame with Lighting

Add glowing borders using emissive materials and tube rendering.

var borderModel = THREE.commonFunc.borderLight(serverId);

3.1 Micro-Module Assembly

Arrange cabinets in two rows with spacing equal to 2.5 times cabinet thickness. Pass only cabinet position parameters.

/*
 * Retrieve cabinet positions within module
 * position: [{1,1,uuid-xxx}, {1,2,uuid-xxx}, ...]
 */
var microModule = THREE.commonFunc.createMicroModule(serverId);

2. Data Center Environment

Define the room using JSON configuration.

[
  {
    "name": "doorCaseTop",
    "objType": "cube",
    "length": 220, "width": 24, "height": 5,
    "x": -300, "y": 220, "z": -350,
    "style": { "skinColor": 9095650, "skin": { "skin_behind": { "skinColor": 13819101 } } }
  },
  {
    "name": "Leftwall",
    "objType": "cube",
    "length": 20, "width": 810, "height": 240,
    "x": 490, "y": 120, "z": 50,
    "style": { "skinColor": 9095650 }
  },
  {
    "name": "Rightwall",
    "objType": "cube",
    "length": 20, "width": 810, "height": 240,
    "x": -490, "y": 120, "z": 50,
    "style": { "skinColor": 9095650 }
  },
  {
    "name": "forewall",
    "objType": "holeCube",
    "length": 1000, "width": 20, "height": 240,
    "x": 0, "y": 120, "z": -350,
    "childrens": [
      { "name": "doorhole", "objType": "cube", "width": 20, "height": 220, "length": 220, "x": -300, "y": -10, "z": 0 },
      { "name": "windowHole", "objType": "cube", "width": 20, "height": 160, "length": 500, "x": 200, "y": 10, "z": 0 }
    ]
  },
  {
    "name": "floor_2",
    "objType": "cube",
    "length": 1800, "width": 1600, "height": 10,
    "x": 32.156, "y": -8.708, "z": 11.662,
    "style": {
      "skin": {
        "skin_up": { "imgurl": "../../img/3dImg/grasslight-big.jpg" }
      }
    }
  }
]

Other environment elements include:

  • Fire extinguishers (loaded from external OBJ JSON)
  • Air conditioners (cube with texture)
  • Power distribution cabinets
  • Desks and chairs (built from tubes and cylinders)

3. Functional Logic

3.1 Single Cabinet Inspection

Open cabinet doors and display server layout.

if (modelBussiness.showSingleServerNeedVitures.length > 0) {
  WT3DObj.commonFunc.changeObjsOpacity(modelBussiness.showSingleServerNeedVitures, 0.2, 1, 200, function () {
    $.each(modelBussiness.showCabServers, function (_index, _obj) {
      _obj.visible = true;
    });
  });
}
_this.openCabDoor(_obj);

if (modelBussiness.lastMouseInCurrentObj.name.indexOf("OBJCREN7") > 0 ||
    modelBussiness.lastMouseInCurrentObj.name.indexOf("OBJCREN8") > 0) {
  this.commonFunc.opcabinetBackLeftdoor(_obj.doors.leftDoor);
  this.commonFunc.opcabinetBackRightdoor(_obj.doors.rightDoor);
} else if (modelBussiness.lastMouseInCurrentObj.name.indexOf("OBJCREN9") > 0) {
  this.commonFunc.opcabinetMaindoor(_obj.doors.mainDoor);
}

setTimeout(function () {
  if (_obj.doors.leftDoor.doorState === undefined || _obj.doors.leftDoor.doorState === "close") {
    if (_obj.doors.rightDoor.doorState === undefined || _obj.doors.rightDoor.doorState === "close") {
      if (_obj.doors.mainDoor.doorState === undefined || _obj.doors.mainDoor.doorState === "close") {
        modelBussiness.commonFunc.showCabnetDetail(_obj, function () {});
      }
    }
  }
}, 200);

3.2 Micro-Module Analytics

Display heat maps, space utilization, power, cooling, and load metrics.

{
  btnid: "btn_space",
  btnTitle: "Cabinet Utilization",
  btnimg: "../../img/3dImg/space.png",
  sortnub: 0,
  btnType: "system",
  enable: true,
  show_event: function () {
    if (modelBussiness.lock == true) {
      layer.tips("Currently running: " + modelBussiness.currentLockDetail, "#btn_space");
      return;
    }
    modelBussiness.currentLockDetail = "Cabinet Utilization";
    modelBussiness.lock = true;
    setTimeout(function () { modelBussiness.lock = false; }, 2000);
    modelBussiness.showSpaceRate();
  }
},
{
  btnid: "btn_temperature",
  btnTitle: "Temperature Heatmap",
  btnimg: "../../img/3dImg/temperature.png",
  sortnub: 0,
  btnType: "system",
  enable: true,
  show_event: function () {
    if (modelBussiness.lock == true) {
      layer.tips("Currently running: " + modelBussiness.currentLockDetail, "#btn_temperature");
      return;
    }
    modelBussiness.currentLockDetail = "Temperature Heatmap";
    modelBussiness.lock = true;
    setTimeout(function () { modelBussiness.lock = false; }, 2000);
    modelBussiness.showTemptureMap();
  }
}

3.3 Server Decommissioning

var _this = modelBussiness;
_this.currentShowServerNames = [];
var cabinetName = cabinetobj.name;
if (_this.Devs[cabinetName] && _this.Devs[cabinetName].devs && _this.Devs[cabinetName].devs.length > 0) {
  $.each(_this.Devs[cabinetName].devs, function (_index, _obj) {
    _obj.visible = true;
    _this.currentShowServerNames.push(_obj.name);
  });
} else {
  var devJsonModels = [];
  if (devs && devs.length > 0) {
    $.each(devs, function (_index, _obj) {
      var height = (_obj.devURange.max - _obj.devURange.min + 1) * 8.2;
      var positiony = height / 2 + 42 + (_obj.devURange.min - 1) * 8.5;
      var postioinx = cabinetobj.position.x;
      var postioinz = cabinetobj.position.z;
      var rotationy = cabinetobj.rotation.y + Math.PI;
      var name = cabinetobj.name + "_Server_" + _index;
      if (!_obj.devCustomSkin) {
        var skins = ["../img/3dImg/server2.jpg", "../img/3dImg/server3.jpg", "../img/3dImg/server1.jpg"];
        _obj.devCustomSkin = {
          up: "../img/3dImg/rack_inside.jpg",
          down: "../img/3dImg/rack_inside.jpg",
          fore: skins[parseInt(Math.random() * 3)],
          behind: skins[parseInt(Math.random() * 3)],
          left: "../img/3dImg/server_side.jpg",
          right: "../img/3dImg/server_side.jpg"
        };
      }
      var server = getSingleServerModel(cabinetobj.name + "_Server_" + _index, { "x": postioinx, "y": positiony, "z": postioinz }, height, rotationy, _obj.devId, _obj.devCustomSkin);
      server.BindDevId = _obj.devId;
      devJsonModels.push(server);
      _this.currentShowServerNames.push(name);
    });
    WT3DObj.commonFunc.loadModelsByJsons(devJsonModels, { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 }, true);
    _this.Devs[cabinetName] = {
      devs: WT3DObj.commonFunc.findObjectsByNames(_this.currentShowServerNames)
    };
  }
}

3.4 Server Commissioning

if (_this.needHideCabinets.length > 0) {
  WT3DObj.commonFunc.changeCameraPosition({ x: 2531, y: 3967, z: -1150 }, { x: -615, y: 0, z: -35 }, 1000, function () {
    $.each(_this.needHideCabinets, function (_index, _obj) {
      if (_obj.name.indexOf("_rate_") < 0 && _obj.name.indexOf("_yearCube_") < 0) {
        _obj.visible = true;
      }
    });
  });
}
if (_this.needHideobjs.length > 0) {
  _this.hideDevs();
  WT3DObj.commonFunc.changeCameraPosition({ x: 2531, y: 3967, z: -1150 }, { x: -615, y: 0, z: -35 }, 1000, function () {
    $.each(_this.needHideobjs, function (_index, _obj) {
      if (_obj.name.indexOf("TCL_line_") < 0 && _obj.name.indexOf("_wind") < 0) {
        _obj.visible = true;
        if (_obj.children && _obj.children.length > 0) {
          $.each(_obj.children, function (_cindex, _cobj) {
            _cobj.visible = true;
          });
        }
      }
    });
    if (_this.currentShowCabinet) {
      _this.currentShowCabinet.visible = false;
    }
    WT3DObj.commonFunc.changeObjsOpacity(_this.needHideobjs, 0.01, 1, 1000, function () {
      _this.hideLines();
      _this.hideWinds();
      _this.hideUsageSpaceRate();
      _this.hideSpaceRate();
    });
  });
}

3.5 Scheduled Server Operations

layer.closeAll();
console.log(result);
var cabNoUse = {};
if (result && result.length && result.length > 0) {
  $.each(result, function (_index, _obj) {
    var _cab = wtserverAPI.getCabinetByUUID(modelBussiness.roomName, _obj.cabid);
    if (_cab && _cab.cabName) {
      var ageValue = [];
      if (_obj.uPositionUsed && _obj.uPositionUsed.length && _obj.uPositionUsed.length > 0) {
        for (var j = 0; j < _obj.uPositionUsed.length - 1; j++) {
          if (j == 0) {
            ageValue.push({ value: 1, max: _obj.uPositionUsed[0], min: _obj.uPositionUsed[0] });
          }
          if (_obj.uPositionUsed[j + 1] - _obj.uPositionUsed[j] > 1) {
            ageValue.push({ value: 1, max: _obj.uPositionUsed[j + 1], min: _obj.uPositionUsed[j + 1] });
          } else {
            ageValue[ageValue.length - 1].max = _obj.uPositionUsed[j + 1];
          }
        }
      }
      cabNoUse[_cab.cabName] = ageValue;
    }
  });
}
console.log(cabNoUse);
for (var i = 0; i < allCabs.length; i++) {
  var itcobj = WT3DObj.commonFunc.findObject(allCabs[i]);
  var ageValue = [];
  if (cabNoUse[allCabs[i]]) {
    ageValue = cabNoUse[allCabs[i]];
  }
  var style = { borderColor: 0x4444, outColor: 0xFFFFFF, outOprity: 0.1 };
  if (itcobj) {
    _this.commonFunc.createUseageCube(allCabs[i],
      { x: 160, y: 380, z: 140 },
      { x: itcobj.position.x, y: itcobj.position.y, z: itcobj.position.z },
      { x: 0, y: 0, z: 0 },
      ageValue,
      style, { timelogn: 1000 }, i);
  }
}

Tags: Three.js 3D Data Center Micro-Module WebGL Cabinet Visualization

Posted on Thu, 05 Nov 2026 16:48:14 +0000 by cfemocha