wedge

Recently, I have to do a visual presentation project of base station. We first tried 3d visualization technology to program, but the customer feedback is that their client computer is poor, performance and efficiency is not good, even some of the cloud host. Therefore, we first made a 3Ddemo with extreme performance, as shown below:

In order to achieve the best performance possible, various performance optimization methods were considered. Of course, there will also be a discount in the effect. Compared with some of our products, such as 3D computer room, there must be a big gap in the effect of this demo. But the performance is pretty good. However, unfortunately, after getting the demo test, the customer was not satisfied… . The performance was ok, but they didn’t think it was cool enough.

Configuration is very low, and high performance, and dazzling effect. This can only be reduced to one word:

Seems to be in desperate straits… However, there is always a new place to live, and there are always new hopes and new opportunities.

2.5D’s thought spark

What comes to mind is 2.5D, which is a pseudo-3D effect, but it only shows one lens Angle, not the rotation of the lens.

In fact, we had some early prototypes of 2.5D, such as layered topologies and 2.5D nodes. Layered topologies even date back to the Java era. As shown in the figure below:

Take the previous 2.5D source code and read it. After reading, the general idea: mainly by piecing together three parallelograms to simulate this 3D effect, the technology has no system.

This kind of thinking will be more difficult for the location of the object positioning and alignment, the development difficulty itself is also relatively large, in addition to achieve some good results, the difficulty is also relatively large, to know that the customer’s requirements for the effect is not low.

So you need to come up with new technical ideas, preferably systematic ideas, and get rid of previous technical ideas. Of course, it was not easy. I didn’t have any good ideas at that time, and I had a lot of doubts and confusion. For many days afterwards, it was like this.

The turning point was a business trip.

On the way back to the hotel after visiting a big customer, I was walking on the road when an idea popped into my mind. Why not use THE 3D thinking and part of the algorithm? What 2.5D wants to present is the 3D effect? The so-called 2.5D, as the name suggests, is to take a few spoonfuls of 2D technology, then take a few spoonfuls of 3D technology, and put them into the pot to fry, why limited to 2D technology.

I have been studying 3D technology for many years, and I am quite skilled in 3D related technology. Suddenly, everything seems to come to my mind, and a set of systematic 2.5D technology begins to take root, sprout and grow in my heart.

My heart was delighted. (But the surface is calm)

This thing tells us a truth, do not be stuck in the problem, go out more, maybe you will think it through. 😄

Next, I confidently communicated with the customer and started to write the relevant technical verification demo, some of which will be explained later. The demo was finally recognized by the customer, and finally we won the project.

For me, creating a 2.5D-related technical system is a small achievement. It’s a creation, and creation is a pleasant thing.

2.5D Technology overview

The so-called 2.5D is to achieve 3D rendering effect through 2D rendering technology. And for this, there is bound to be some USE of 3D technology:

  • The definition of three dimensional space
  • Definition of the model (using 3d space coordinates to define the model)
  • The projection algorithm converts the three – dimensional coordinates into two – dimensional coordinates.

Definition of three-dimensional space

In order to achieve the 2.5D effect, we need to extend the original plane two-dimensional space to three-dimensional space. There are three axes of X, Y and Z in the three-dimensional space, and there is one more Z axis than the original two-dimensional space.

Of course, the three dimensional space definition is for model definition, model location and subsequent projection algorithm. The final drawing will go back to two dimensions.

The model definition

In true 3D, the model needs to be defined through a model file such as OBj. In 2.5D, you only need to define a cube model. As mentioned earlier, 2.5D represents only one face of a 3d object at an Angle, so its model only needs a picture of that face, and the picture is the model.

A cube model is defined so that the images can be placed in the right position and the appropriate size and aspect ratio are constrained. This has important implications for the placement and alignment of models. The cube here is kind of the bounding body of the real model.

You define a cube by specifying attributes such as width, height, and depth. The code looks like this:

  setSize3: function(w, h, d) {
    var oldValue = {
      w: this._width3,
      h: this._height3,
      d: this._depth3,
    };
    this._width3 = w;
    this._height3 = h;
    this._depth3 = d;
    this.firePropertyChange('size3', oldValue, { w: w, h: h, d: d });
  },Copy the code

You can also specify the three-dimensional coordinates of the cube as follows:

 setPosition: function(x, y, z) {
    var oldValue = this.getPosition();
    this._position = {
      x: x,
      y: y,
      z: z,
    };
    this.firePropertyChange('position', oldValue, this._position);
  },Copy the code

Projection algorithm.

Projection algorithm is an important part of 3D graphics. Projection algorithm mainly includes perspective projection algorithm and parallel projection algorithm. In 2.5D, parallel projection is required (and only the parallel projection algorithm can be used)

The projection algorithm is the key step.

To define the projection algorithm, we first simulate a parallel shot, define the position and Angle of the shot through the parallel shot, and define a projection matrix by these parameters:

/** ** Calculate the transformation matrix, the transformation matrix is determined by the camera parameters */ calMVMatrix: function() { var angle = this.getAngle3(), vAngle = this.getVAngle3(), radius = this.getRadius3(), viewMatrix = mat4.create(), projectMatrix = mat4.create(), mvMatrix = mat4.create(), winWidth = 1, winHeight = 1; mat4.lookAt( viewMatrix, [ radius * Math.cos(vAngle) * Math.sin(angle), -radius * Math.sin(vAngle), radius * Math.cos(vAngle) * Math.cos(angle), ], [0, 0, 0], [0, 1, 0] ); Ortho (projectMatrix, -winwidth / 2, winWidth / 2, -winheight / 2, winHeight / 2, 0.1, 1000); mat4.multiply(mvMatrix, projectMatrix, viewMatrix); this.mvMatrix = mvMatrix; },Copy the code

In the above code, the gl-matrix.js package was used to define the projection matrix.

After the projection matrix is defined, the position of each vertex on the cube on the plane coordinates can be calculated by the projection algorithm:

P 5 - p8 ** p8 p7 ** p5 p6 ** p4 p3 ** p1 p2 ** / var points1 = [{x: -w3 / 2 + pos.x, y: -h3 / 2 + pos.y, z: d3 / 2 + pos.z, }, // p1 { x: w3 / 2 + pos.x, y: -h3 / 2 + pos.y, z: d3 / 2 + pos.z, }, // p2 { x: w3 / 2 + pos.x, y: h3 / 2 + pos.y, z: d3 / 2 + pos.z, }, // p3 { x: -w3 / 2 + pos.x, y: h3 / 2 + pos.y, z: d3 / 2 + pos.z, }, // p4 { x: -w3 / 2 + pos.x, y: -h3 / 2 + pos.y, z: -d3 / 2 + pos.z, }, // p5 { x: w3 / 2 + pos.x, y: -h3 / 2 + pos.y, z: -d3 / 2 + pos.z, }, // p6 { x: w3 / 2 + pos.x, y: h3 / 2 + pos.y, z: -d3 / 2 + pos.z, }, // p7 { x: -w3 / 2 + pos.x, y: h3 / 2 + pos.y, z: -d3 / 2 + pos.z, }, // p8 ]; var points = (this._points = []); points1.forEach(function(point) { var newPoint = self.getPositionByRotate( point, pos, rotationX, rotationY, rotationZ ); points.push({ x: newPoint[0], y: newPoint[1], z: newPoint[2], }); }); var ps = (this._projectPoints = points.map(function(point) { return self.getProjectionPoint(point); }));Copy the code

Once you have a projection point of 8 vertices, you can draw a border effect, you can draw a color fill effect, or you can draw an image fill effect.

Draw border effect

Arrange the points on several surfaces in order to create the effect of a border. The following code looks like this:

drawPoints: function (ctx, points, close, dash, fill, borderColor, image) {if (! points || points.length == 0) {return; }ctx.beginPath(); ctx.strokeStyle = “black”; if (borderColor) {ctx.strokeStyle = borderColor; }ctx.lineWidth = 1; CTX. FillStyle = ‘RGB (102204255); if (dash) {ctx.setLineDash([4, 4]); CTX. StrokeStyle = ‘rgba (0,0,0,0.5); } else {ctx.setLineDash([1, 0]); }ctx.moveTo(points[0].x, points[0].y);

        for (var i = 1; i < points.length; i++) {
            var p = points[i];
            ctx.lineTo(p.x, p.y);
        }Copy the code
        if (close) {
            ctx.lineTo(points[0].x, points[0].y);
        }Copy the code
ctx.closePath(); ctx.stroke(); } The final drawing effect is as shown in the figure below:Copy the code

Draws the color fill effect

To draw a cube filled with color, just add this line of code to the drawing above:

  if (fill) {
            ctx.fill();
            // drawImageInPoints(ctx, image, points);
        }Copy the code

The final drawing effect is as follows:

Draw pictures

When drawing the picture, it is not necessary to draw the picture for every face, but only to draw the picture into the area occupied by the 8 vertices projected by the cube. What is needed is that the 8 vertices coincide with the vertices of the picture, as shown in the figure below:

Firstly, the size of the two-dimensional region occupied by the projected vertices is calculated:

/** @param {Array} points ** @returns {Object} -rect */ getRect: function(points) { var minX, minY, maxX, maxY; points.forEach(function(point) { if (minX == null) { minX = maxX = point.x; minY = maxY = point.y; } else { minX = Math.min(minX, point.x); maxX = Math.max(maxX, point.x); minY = Math.min(minY, point.y); maxY = Math.max(maxY, point.y); }}); return { x: minX, y: minY, width: maxX - minX, height: this.getElement().getClient('reflect') ? (maxY - minY) * 2 : maxY - minY, }; },Copy the code

Then draw the image directly in the area:

 ctx.drawImage(
            image,
            0,
            image.height - 20,
            image.width,
            20,
            rect.x,
            rect.y + rect.height - 20,
            rect.width,
            20
          );Copy the code

The final drawing effect is as follows:

Build the ground and wall

With the cube model, you can build the floor and wall scene effect, because the floor and wall can be composed of cubes. Therefore, it can be easily built. All you need to do is to set the size of the related cube model and add it to the scene:

var node1 = new twaver.Node2_5({ styles: { 'body.type': 'vector', }, name: 'TWaver', centerLocation: { x: 300, y: 200 }, width: 800 / 1, height: 360 /.775, }); node1.setImage(null); Node1. SetPosition (00,0,100); node1.setWidth3(1000); node1.setHeight3(10); node1.setDepth3(1200); // node1.setStyle('top.image','image0'); // node1.setstyle ('top.image.rule','pattern'); // node1.setstyle ('top.image.rule','pattern'); // node1.setClient('receiveShadow',true); box.add(node1); var node1 = new twaver.Node2_5({ styles: { 'body.type': 'vector', }, name: 'TWaver', }); node1.setImage(null); Node1. SetPosition (250155, 500); node1.setWidth3(500); node1.setHeight3(300); node1.setDepth3(1); box.add(node1); var node1 = new twaver.Node2_5({ styles: { 'body.type': 'vector', }, name: 'TWaver', }); node1.setImage(null); Node1. SetPosition (250105-500); node1.setWidth3(500); node1.setHeight3(200); node1.setDepth3(1); node1.setStyle('front.image','weilan'); // ToDo defines the style rule box.add(node1);Copy the code

The final display is as follows:

The mapping of the ground and the lighting effect of the wall will be explained later.

Here’s the story of the first play. Let’s take a look at the overall effect:

Welcome to follow the public account “ITman Biao Uncle”. Uncle Biao, with more than 10 years of development experience, the current company system architect, technical director, technical trainer, career planner. In-depth research in computer graphics, WebGL, front-end visualization. Strong interest in programmer thinking ability training and training, programmer career planning.