3D model intersection and supplement of WebGL

Keywords: Front-end Attribute Windows css3

Constructive Solid Geometry has many practical applications. It is used in the case of simple geometric objects, or where mathematical accuracy is very important. Almost all engineering CAD software packages use CSG (which can be used to represent cutting tools and the features that parts must fit together). CSG is the abbreviation of Constructive Solid Geometry modeling technology. It combines complex model effect by cutting sub-contract, merging union and intersect ing operation. HT encapsulates the elements such as ht.CSGNode and ht.CSGShape to support the combination function of CSG, which is commonly used in the application scenario of hollowing and hole digging of wall doors and windows.

CSG objects can be represented by binary trees, in which leaves represent primitives and nodes represent operations. In this graph, nodes are marked ∩ as intersection, ∪ as union and - as difference. CSG provides models or surfaces that look complex, but are really nothing more than clever combinations or decomposition of objects.

ht.CSGNode inherits from ht.Node. When the shape3d attribute of style is empty, it will be displayed as a hexahedral effect. If CSGNode is adsorbed to the host CSGNode or CSGShape through setHost, the host CSGNode or CSGShape can be combined with the adsorbed CSGNode entity for CSG modeling. Refer to the CSGNode section of the HT for Web Modeling manual for details. Here I use the concept of CSG to write an example, so that you can better understand this concept.

In this example, Demo address: hightopo.com/guide/guide...

First, let's look at the following renderings:

From the above rendering, we can see that the interface is divided into three parts. First, the right part is divided up and down, and then the whole interface is divided left and right. HT uses the encapsulated ht.widget.SplitView to split the interface, and then adds the split component to the underlying div:

dm = new ht.DataModel();// data model            
treeView = new ht.widget.TreeView(dm); //Tree component                                                                                                 
gv1 = new ht.graph3d.Graph3dView(dm); //3D component  
gv2 = new ht.graph3d.Graph3dView(dm);
splitView = new ht.widget.SplitView(gv1, gv2, 'v', 0.6);//Segmentation component 
mainSplit = new ht.widget.SplitView(treeView, splitView, 'h', 0.27);   
                
view = mainSplit.getView();  
view.className = 'main';
document.body.appendChild(view);    
window.addEventListener('resize', function (e) {
    mainSplit.invalidate();
}, false);     

The above code is a very common way to add HT components to HTML. Please refer to the components section of the HT for Web getting started manual for details. There is a point to pay attention to when adding HT components in this way, because HT generally uses the absolute positioning method of setting position as absolute. It is necessary to set the basic css styles such as left, right, top, bottom, etc., as follows:

.main {
     margin: 0px;
     padding: 0px;
     position: absolute;
     top: 0px;
     bottom: 0px;
     left: 0px;
     right: 0px;
}

Therefore, for the convenience of loading and filling the window with the outermost components, all components of HT have addToDOM functions. The logic is as follows, where iv is the abbreviation of invalidate:

addToDOM = function(){   
    var self = this,
    view = self.getView(),   
    style = view.style;
    document.body.appendChild(view);            
    style.left = '0';
    style.right = '0';
    style.top = '0';
    style.bottom = '0';      
    window.addEventListener('resize', function () { self.iv(); }, false);            
}

In the future, we can directly call addToDOM function in the code, instead of writing a lot of code. The code after the above code is replaced by addToDOM is as follows, and we do not need to describe css Style:

dm = new ht.DataModel();// data model             
treeView = new ht.widget.TreeView(dm); //Tree component                                                             
gv1 = new ht.graph3d.Graph3dView(dm); //3D component  
gv2 = new ht.graph3d.Graph3dView(dm);
splitView = new ht.widget.SplitView(gv1, gv2, 'v', 0.6);//Segmentation component 
mainSplit = new ht.widget.SplitView(treeView, splitView, 'h', 0.27);   
mainSplit.addToDOM();

After the interface is allocated, we will add content to it. The left part of the interface is the HT encapsulated tree component. As I wrote in the previous article, the tree component is a very convenient component for drawing tree relationship. Developers can easily get the relationship between data and nodes from the data model DataModel and put it on the tree, only in the process of tree component declaration Put the corresponding data model DataModel into the parameters of the tree component. Of course, we have expanded many functions related to the tree component, which is very convenient and practical. Here we only use the expandAll function to expand all objects:

treeView = new ht.widget.TreeView(dm); //Tree component   
treeView.expandAll();

The upper and lower parts of the right part are divided into two parts. They are all 3D scenes. That is, the settings and display are a little different. The other parts are identical. The above 3D scene overloads the getVisibleFunc function. If the showMe attribute of the element is true, it can be seen. If the node is of type ht.CSGNode and the parameter of the getHost function of the node is empty, it can not be seen. In other cases, it can be seen:

gv1.setVisibleFunc(function(data){
    if(data.showMe){
        return true;
    }
    if(data instanceof ht.CSGNode && data.getHost()){
        return false;
    }
    return true;
});

First, we add element objects to the 3D scene. First, we explain the bookshelf in the middle, and then supplement the bookshelf on both sides. First, we add a ht.CSGNode node shelf as the main node of the shelf, and other nodes are attached to this node. We set the location, size, name and six face colors for this node, and then add it to the data model DataModel:

var shelf = new ht.CSGNode();
shelf.s3(500, 400, 120);
shelf.p3(0, 200, 0);
shelf.setName('shelf1');
shelf.s({
    'all.color': '#E5BB77'
});
dm.add(shelf);

Then add 10 nodes to the shelf to make the lattice effect of the shelf, and set the dependency relationship and parent-child relationship to add to the data model:

for(var i=0; i<2; i++){
    for(var j=0; j<5; j++){
        var clipNode = new ht.CSGNode();
        clipNode.setHost(shelf);
        clipNode.s3(80, 100, 120);
        clipNode.p3(-200+j*100, 340-i*120, 20);
        clipNode.setName('substract-'+i+'-'+j);
        clipNode.s('batch', 'tt');
        clipNode.setParent(shelf);
        dm.add(clipNode);
    }
}

In order to make the bookshelf more beautiful, we have added ht.CSGNode on the top, bottom, left and right sides of the bookshelf. Finally, in order to make it more concrete, we have added a book with similar implementation methods, which are very simple:

var book = new ht.Node();
book.setName('CSS3: The Missing Manual');
book.s3(60, 80, 8);
book.p3(-100, 210, 20);
book.r3(-Math.PI/6, Math.PI/5, 0);
book.setIcon('book');
book.s({
    'front.image': 'book',
    'back.color': 'white',
    'left.color': 'white',
    'all.color': 'gray'
});
book.setHost(shelf);
book.setParent(shelf);
dm.add(book); 

Then the bookshelf on the left is similar to the construction method. One difference is that there is a ht.CSGBox type inherited from ht.CSGNode, which has the function of hollowing out the parent CSGNode, and can also rotate and expand and close six faces. Here, our node only sets the previous one that can rotate and expand, and sets a series of styles:

clipNode = new ht.CSGBox();
clipNode.setName('CSGBox-Expand-Left');
clipNode.s3(100, 100, 120);
clipNode.p3(0, 65, 0.1);
clipNode.setHost(shelf);
clipNode.showMe = true;
clipNode.s({
    'all.visible': false,//6 sides are invisible
    'front.visible': true,//Visible ahead
    'front.toggleable': true,//Allow double click to expand                    
    'front.reverse.flip': true,//The front and the back show the front
    'front.transparent': true,//Transparent front
    'front.end': Math.PI * 0.7,//End rotation radian of front expanded state
    'front.color': 'rgba(0, 50, 50, 0.7)'//Front color
});

Maybe you want to know how the earth below does it? Remember that the previous article wrote that the shape3d attribute was set in HT. To set this attribute is actually to operate setShape3dModel(name, model) and getShape3dModel(name), which can be set to box|sphere|cylinder|cone|torus|star|rect|roundrect|triangle|righttriangle|parallelogram|tracezoid and other models. These models are also encapsulated by HT For example, "shape3d: sphere" in this example is set as a sphere. We simply wrap a map image around the outside of the sphere. Of course, this map image was registered by ht.Default.setImage, and then attached to this node by shape3d.image

earth = new ht.Node();
earth.setName('earth');
earth.s3(70, 70, 70);
earth.p3(0, 50, 0);
earth.s({
    'shape3d': 'sphere',
    'shape3d.image': 'earth'
});
earth.setHost(shelf);  
earth.setParent(shelf);
dm.add(earth);

The bookshelf on the right also has a master node, and other nodes are attached to it. However, we see that a new node type ht.DoorWindow is changed here. Ht.DoorWindow inherits from ht.CSGNode. In addition to the function of hollowing out the parent CSGNode, it can also carry out the operation of overall rotation expansion and closing. It is often used as the business object of a door or window and adsorbed on CSGNode Or the host of CSGShape is the element of the wall. This node type is the extension of ht.CSGNode, which is relatively different from the actual application and adds different style parameters. For more attributes, please refer to the DoorWindow chapter of the HT for Web Modeling manual and add them to the node

photos = new ht.DoorWindow();
photos.setName('DoorWindow-Photos');
photos.setIcon('ben12');
photos.s3(110, 100, 130);
photos.p3(5, 180, 0);                
photos.setHost(shelf);  
photos.showMe = true;
photos.s({                    
    'bottom.uv': [1,1, 1,0, 0,0, 0,1],
    'bottom.uv.scale': [1, 1],
    'left.uv.scale': [3, 3],
    'top.uv.scale': [2, 2],
    'dw.s3': [0.8, 0.9, 0.05],
    'dw.t3': [0, -5, 0],
    'dw.axis': 'v',
    'dw.toggleable': false,
    'front.image': 'ben1',
    'back.image': 'ben2',
    'all.color': '#F8CE8B'
});
photos.setParent(shelf);
dm.add(photos);

Finally, we rotate the earth on the left and the photo on the right:

var angle = 0;
setInterval(function(){
    angle += Math.PI/40;
    earth.r3(0, angle, 0);
    photos.s('dw.angle', angle);
}, 50);

We can see that although HT encapsulates many different types of CSG nodes, the actual applications are almost the same, and the content is not much different, the differences are all in the style parameters, but really in the actual development, this kind of distinction will greatly speed up the development speed, after all, the name is clear at a glance, and we know which style attributes to use.

Posted by GoncaloF on Wed, 25 Dec 2019 10:26:49 -0800