简体   繁体   中英

How to create parallelogram using Aframe js?

I have been trying to create a parallelogram using Aframe js but i couldn't find primitive to create. Please help me to create it.

You could make it manually, by creating a custom component , which will create a mesh based on a custom THREE.js shape:

let points = [];
points.push(new THREE.Vector2(0, 0));
points.push(new THREE.Vector2(3, 0));
points.push(new THREE.Vector2(5, 3));
points.push(new THREE.Vector2(2, 3));

for (var i = 0; i < points.length; i++) {
  points[i].multiplyScalar(0.25);
}
var shape = new THREE.Shape(points);
var material = new THREE.MeshBasicMaterial({
  color: 0x00ff00
});
var mesh = new THREE.Mesh(geometry, material);
this.el.object3D.add(mesh);

working fiddle here . Please check out this question as well.

Here is how I would create any custom shape that I wanted (using parallelogram as example), although Piotr's answer is much more succinct, maybe another approach will be helpful.

First create a custom component that contains all the vertices you need for your shape. (Sorry that vertices makes it long but its clearer whats going on)

//register parallelogram component

AFRAME.registerComponent('parallelogram', {

//create schema
schema: {    
},

//define vertices of a parallelogram
//made up of 4 triangles that are combined together
para_vertices: [
    //first triangle
    {
        'x': -1,
        'y': 0,
        'z': 0,
    },
    {
        'x': 0,
        'y': 0,
        'z': 0,
    },
    {
        'x': 0,
        'y': 1,
        'z': 0,
    },
    //second triangle
    {
        'x': 0,
        'y': 0,
        'z': 0,
    },
    {
        'x': 1,
        'y': 0,
        'z': 0,
    },
    {
        'x': 0,
        'y': 1,
        'z': 0,
    }, 
    //third triangle  
    {
        'x': 1,
        'y': 0,
        'z': 0,
    },
    {
        'x': 1,
        'y': 1,
        'z': 0,
    },
    {
        'x': 0,
        'y': 1,
        'z': 0,
    },
    //fourth triangle  
    {
        'x': 1,
        'y': 0,
        'z': 0,
    },
    {
        'x': 2,
        'y': 1,
        'z': 0,
    },
    {
        'x': 1,
        'y': 1,
        'z': 0,
    }, 

],


init: function (){

    //create 3.js geometry      
    this.geometry = new THREE.Geometry();
    var geometry = this.geometry

    //get the vertices that we described above
    var verts = this.para_vertices
    //calculate number of faces     
    var faceCount = verts.length/3

    //loop through vertices and add to the geometry
    for (var i = 0; i < verts.length; i++) {
        var v3 = verts[i]
        geometry.vertices.push ( new THREE.Vector3(v3.x, v3.y, v3.z) );
    }
    //add faces to geometry 
    for (var i = 0; i < faceCount; i++) {
        a = i+i*2
        geometry.faces.push(new THREE.Face3(a, a+1, a+2))
    }
    geometry.computeBoundingBox();
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();
    geometry.mergeVertices();

    //use out of the box material that you add to the entity in the primitive below
    this.material = this.el.components.material.material
    //make a new 3.js mesh combining the geometry and the material
    this.mesh = new THREE.Mesh(this.geometry, this.material);
    //add this mesh to our parent element
    this.el.setObject3D('mesh', this.mesh);

},

});

Then, make a primitive by using that component and the existing material component

//make it a primitive by defining a-parallelogram and adding the above component
AFRAME.registerPrimitive('a-parallelogram', {
  defaultComponents: {
    //add the material component
    // you could define this yourself in the above component if you prefer
    material: {},
    //add the parallelogram component we have just created
    parallelogram: {},
  },
  mappings: { 
    //specify any attributes and their mappings that you would like to be able to define from the html layer
    color: 'material.color',
  }, 
});

And you can then use that in your HTML like so

<html>
  <head>
    <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script>
    <!-- include a script that contains the parallelogram component -->
    <script src="scripts/parallelogram.js"></script>
  </head>
  <body>
    <a-scene>
        <a-parallelogram position="-1 0.5 -5" color="blue"></a-parallelogram>
        <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
        <a-sky color="#ECECEC"></a-sky>
    </a-scene>
  </body>
</html>

Here is a working fiddle

I hope that's helpful, you can find more on creating custom components here and in particular for making shapes here

Alternatively, here is another approach that separates the 'shapemaker' from the 'shapedata' so you can just have one script for making whatever custom shape you like and add in the shape-specific data by registering a custom primitive (that uses that component) and passing the shape-specific information from there.

So, a generic shapemaker component (will parse the vertices in the schema when passed from the primitive registration)

//register custom shape maker component
AFRAME.registerComponent('customshape', {

    schema: {
        model: {
            default: {},
            parse : function (value){  
                return value
            }
        },   
    },    

    init: function (){

        this.geometry = new THREE.Geometry();
        var geometry = this.geometry
        var verts = this.data.model
        var faceCount = verts.length/3
        for (var i = 0; i < verts.length; i++) {
            var v3 = verts[i]
            geometry.vertices.push(new THREE.Vector3(v3.x, v3.y, v3.z));
        }       
        for (var i = 0; i < faceCount; i++) {
            a = i*3
            geometry.faces.push(new THREE.Face3(a, a+1, a+2))
        }
        geometry.computeBoundingBox();
        geometry.computeFaceNormals();
        geometry.computeVertexNormals();
        geometry.mergeVertices();   
        this.material = this.el.components.material.material
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.el.setObject3D('mesh', this.mesh);

    },

});

Then register whatever shape you want as a primitive (eg parallelogram) and pass in the vertices as a value when you assign the default components

//register particular shape primitive and pass in shape specific vertices
AFRAME.registerPrimitive('a-parallelogram', {
  defaultComponents: {
    material: {},
    customshape: {model: [
        {
            'x': -1,
            'y': 0,
            'z': 0,
        },
        {
            'x': 0,
            'y': 0,
            'z': 0,
        },
        {
            'x': 0,
            'y': 1,
            'z': 0,
        },
        {
            'x': 0,
            'y': 0,
            'z': 0,
        },
        {
            'x': 1,
            'y': 0,
            'z': 0,
        },
        {
            'x': 0,
            'y': 1,
            'z': 0,
        }, 
        {
            'x': 1,
            'y': 0,
            'z': 0,
        },
        {
            'x': 1,
            'y': 1,
            'z': 0,
        },
        {
            'x': 0,
            'y': 1,
            'z': 0,
        },
        {
            'x': 1,
            'y': 0,
            'z': 0,
        },
        {
            'x': 2,
            'y': 1,
            'z': 0,
        },
        {
            'x': 1,
            'y': 1,
            'z': 0,
        }, 

    ],
},
  },
  mappings: { 
    color: 'material.color',
  }, 
});

And then use that in the HTML

<html>
  <head>
    <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script>
    <script src="scripts/simplecustomshapemaker.js"></script>
  </head>
  <body>
    <a-scene>
        <a-parallelogram position="-1 0.5 -5" color="blue"></a-parallelogram>
        <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
        <a-sky color="#ECECEC"></a-sky>
    </a-scene>
  </body>
</html>

So by using that same custom shapemaker script I could define a number of shapes as primitives without having to change that script.

Here is a working fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM