How to create 3D models (e.g. irregular floors) with javascript
Tags: javascript, webgl, 3d, webdev
Published: 2022-11-14 14:27:55

The floors we finally created in browser:
![2d/3d floors](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkroppakfc2nvdxg4z1a.png)

There're multiple ways to create 3D models in browser with Javascript. In this article, we'll talk about one simple way (use [HT for Web](https://www.hightopo.com/demos/en-index.html)) to create a type of basic model: 3D floor by javascript.

## 1. Initialize the 2D/3D environment

At first, we created one data model, which will be used by g2d (GraphView) and g3d (Graph3dView). Since g2d and g3d use the same data model, the properties changed in one environment will be mirrored in the other.

```
dataModel = new ht.DataModel();                
g3d = new ht.graph3d.Graph3dView(dataModel);  // the top canvas 
g2d = new ht.graph.GraphView(dataModel); // the bottom canvas               
mainSplit = new ht.widget.SplitView(g3d, g2d, 'v', 0.4);   

view = mainSplit.getView();  // which is a DIV
view.className = 'main';
document.body.appendChild(view);    
window.addEventListener('resize', function (e) {
    mainSplit.invalidate();
}, false);                         

// 3d configuration
g3d.setGridVisible(true); 
g3d.setEye(0, 400, 400);                          

// 2d configuration
g2d.translate(400, 160);      
g2d.setZoom(0.6, true);
g2d.setEditable(true);                
g2d.setHelperEditableFunc(function(data, helper) {
    return false;                    
});
```

## 2. Prepare the image for the floor

We'll create 3 types of floors, so we defined 3 images (BASE64) here for subsequent shapes to use:

```
ht.Default.setImage('floor1', 'data:image/png;base64,iVB...')
ht.Default.setImage('floor2', 'data:image/png;base64,iVB...')
ht.Default.setImage('grass', 'data:image/jpeg;base64,/9j/4AAQ...')
```

## 3. Create floors

Now the environment and images are ready. Let's add different kinds of shapes.

ht.Shape datas when thickness properties are less than 0 often used to render the floor effect of the polygon model, this type of tall property determines the thickness of the floor, generally through floor.setElevation(floor.getTall()/2); to set the floor on the sea level.

The floor type is controlled the top parameters by the shape3d.top.*, shape3d.bottom.* control of the bottom surface parameters, shape3d.* control of the thickness around the parameters. For situations where only needs the plane and does not requires a stereo effect, you can set the bottom and surround visible parameters of shape3d.bottom.visible and shape3d.visible to false implementations.

GraphView on the 2D ht.Shape realizes tile map can be set through shape.repeat.image property, Graph3dView 3D tiles are controlled by shape3d.top.uv.scale and shape3d.top.bottom.scale, but in this way if the floor size changes, it is generally necessary to set the parameters again so it is not convenient, HT provides the repeat.uv.length parameter to resolve this problem, and by setting this parameter, the tile will automatically adjusts the number of tiles based on the size of the graphic, and also with shape3d.top.uv.scale and shape3d.top.bottom.scale parameters are superimposed, and of course, in most cases, if repeat.uv.length is set, you do not need to set shape3d.top.uv.scale and shape3d.top.bottom.scale parameter.

```
floor1 = new ht.Shape();
dataModel.add(floor1);                   
floor1.setPoints([
    {x: 200, y: 50},
    {x: 400, y: 50},
    {x: 500, y: 200},
    {x: 100, y: 200}
]); 
floor1.translate(-100, -100);
floor1.setClosePath(true); 
floor1.setThickness(-1);
floor1.setTall(10);
floor1.setElevation(floor1.getTall()/2);
floor1.s({
    'shape.border.width': 5,
    'shape.border.color': 'yellow',
    'shape.repeat.image': 'floor1',
    'repeat.uv.length': 256,
    'shape3d.color': 'yellow',
    'shape3d.top.image': 'floor1',
    'shape3d.bottom.image': 'floor1'
});                 

floor2 = new ht.Shape();
dataModel.add(floor2);                   
floor2.setPoints([
    {x: 96, y: 209}, 
    {x: 43, y: 211}, 
    {x: -1, y: 199}, 
    {x: 7, y: 126},
    {x: 54, y: 127}, 
    {x: 41, y: 89}, 
    {x: 98, y: 60}, 
    {x: 114, y: 95},
    {x: 159, y: -3}, 
    {x: 290, y: 66}, 
    {x: 251, y: 137}, 
    {x: 296, y: 155},
    {x: 289, y: 199}, 
    {x: 260, y: 213}, 
    {x: 149, y: 213}, 
    {x: 77, y: 261}
]); 
floor2.setClosePath(true);
floor2.setSegments([1, 2, 4, 4, 4, 4, 2, 2]);
floor2.translate(-400, -100);
floor2.setThickness(-1);
floor2.setTall(30);
floor2.setElevation(floor2.getTall()/2);
floor2.s({
    'shape.border.width': 10,
    'shape.repeat.image': 'floor2',
    'repeat.uv.length': 64,
    'shape3d.top.image': 'floor2',
    'shape3d.bottom.image': 'floor2'
});                                 

grass = new ht.Shape();
dataModel.add(grass);   
grass.setThickness(-1);
grass.setPoints([
    {x: -400, y: -200},
    {x: 400, y: -200},
    {x: 400, y: -100},
    {x: -400, y: -100}
]);
grass.setClosePath(true);                 
grass.setTall(1);
grass.setElevation(1);
grass.s({
    'shape.border.width': 0,
    'shape.repeat.image': 'grass',
    'repeat.uv.length': 128,
    'shape3d.visible': false,                    
    'shape3d.bottom.visible': false,
    'shape3d.top.image': 'grass',
    'shape3d.reverse.flip': true
}); 
```

The demo link and source code can be find here:

(https://www.hightopo.com/guide/guide/core/shape/examples/example_floor.html)

Or people can find the video from: [2d/3d floors](https://youtu.be/CWi4yBOmAP0)