Writing a method yourself is a lot more difficult than analyzing someone else's writing, and the resulting further understanding of the program is hard to get from analyzing someone else's code.
First, a few:
1. There are two spheres with a radius of 1 in the scene, and the Blue Line points from the globe to the "forward" direction of the sphere.
2, the object is selected to change the texture picture and transparency, you can use "W, S, a, d, space, Ctrl" control object relative to the object's forward "front, back, left, right, up, down" move, press and hold the key time the longer the moving speed, Green Line points from the sphere to the direction of the object movement, The faster you expose the surface of the object, press "G" to stop all movements and click on the object again to uncheck the state.
3. You can select multiple objects to move at the same time.
4. When two objects collide, they stop moving, and the red segment is pointed by the object's sphere to the first other object encountered in the direction of motion.
Second, the collision detection principle:
Use Three.raycaster for collision detection because the Raycaster cannot detect the "inner surface" of an object, so a reflection method is used.
Third, the implementation of the program:
Full program code can be downloaded in Http://files.cnblogs.com/files/ljzc002/App2.zip, which includes detailed comments explaining some of the more important paragraphs.
1. Plot the line of motion of the object
1 This. line1;//Own Direction Line2 This. line2;//Motion Direction Line3 This. Line3;//Collision Detection Line4 varVector2= This. V0.clone (). Multiplyscalar (2). Add ( This. object3d.position);//calculates the end point of a segment by a vector5 This. line1= This. CreateLine2 ( This. OBJECT3D.POSITION,VECTOR2,0X0000FF, This. Planetgroup, "line1");//The orientation line of the object in the horizontal direction6 This. line2= This. CreateLine2 ( This. Object3d.position, This. OBJECT3D.POSITION,0X00FF00, This. Planetgroup, "Line2");7 This. line3= This. CreateLine2 ( This. Object3d.position, This. object3d.position,0xff0000, This. Planetgroup, "Line3");
Where point Vector2 is obtained by multiplying the vector v0 by 2 plus this.object3D.position, as the end point of the straight line1. Note that after the V0 ". Clone ()" If removed, the v0 itself will also apply these changes, eventually becoming the same as Vector2.
Line2 and Line3 are initialized to a point.
The "line" object created here has no collision detection function and is purely for viewing.
1 if( This. Speedw! = 0 | | This. Speeda! = 0| | This. speedc!=0)2{//if the object has speed in one Direction3 varvector4=NewThree. Vector3 (0, This. speedc*1000,0);4 varVector3= ( This. V1.clone (). Multiplyscalar ( This. speeda*1000). Add ( This. V0.clone (). Multiplyscalar ( This. speedw*1000) . Add (VECTOR4);5 varVector5=vector3.clone (). Normalize (). Multiplyscalar ( This. Size);6 This. vector3=Vector3.clone (). Add (Vector5);7 This. UpdateLine2 ( This. Line2.uuid,NewThree. Vector3 (0,0,0), This. vector3,0x00ff00);//from the physical body to the direction of movement of the object, make a line of length and speed proportional to the lines8 //Line2 is the child element of Planetgroup, which itself will move with the this.object3D.position, if plus a this.object3D.position to repeat,9 //This is a kind of "relative movement" in some sense.Ten This. Testcollision ();//Collision Detection One //After detection is correct, the next frame position is finalized A if( This. flag_coll==0)//no collisions occurred - { - This. Object3D.position.add ( This. V0.clone (). Multiplyscalar ( This. Speedw)); the This. Object3D.position.add ( This. V1.clone (). Multiplyscalar ( This. Speeda)); - This. OBJECT3D.POSITION.Y + = This. Speedc;//using the equals sign directly will set the failure!! - } - Else + { - This. speeda=0; + This. speedc=0; A This. speedw=0; at This. flag_coll=0;//Reset to a state where no collisions occur -currentlypressedkeys[65]=false; -currentlypressedkeys[68]=false; -currentlypressedkeys[87]=false; -currentlypressedkeys[83]=false; -currentlypressedkeys[32]=false; incurrentlypressedkeys[17]=false; - } to}
Updates the direction and length of the line2 according to the motion of the object. Here the Vector3 is composed of the velocity components of the object in all directions, VECTOR5 is responsible for adjusting the Vector3 to the length of the display, This.vector3 and Vector3 are different objects, representing the displacement of the line2 one endpoint.
UpdateLine2 Update the endpoint of the line2, showing the change in speed. We can see that its two endpoint positional parameters are (0,0,0) and a vector instead of the globe position in the preceding figure and the "point of the globe position plus vector", which shows the relativity between the Three.js parent and son objects. (The simple crash example didn't need to use a sub-object.) )
The example continues from the solar system model in the previous article, the relationship between objects such as:
Planetorbitgroup and Planetgroup are "Object3d" objects, and the "object" has no size, no color attributes but position and attitude attributes (default at the parent object's origin), "Mesh" and "line" Multiple inheritance in Object3d has vertex (geometry), texture (material) attributes.
Planetorbitgroup is the sub-object of scene in the world coordinate system origin, Planetgroup is Planetorbitgroup sub-object is forced to locate in the world coordinate system x=3 place, Globemesh and Line2 are Planetgroup's sub-objects are located at the origin of Planetgroup by default.
When Planetorbitgroup moves (changes this.object3D.position), the moving effect is inherited by all its descendant objects, so we set the line2 vertex to (0, 0,0) automatically inherits the movement effect (this.object3d.position+ (3,0,0)) of all its ancestor elements.
2. Ray-based collision testing
1 var New Three. Raycaster (this. PlanetGroup.position.clone (). Add (the. object3d.position),this. Vector3.clone (). normalize ()); // emits a ray from the center of the object to the actual direction of movement 2 raycaster.far=this. object3d.inter_length; // Ray "Length" 3 var intersects = Raycaster.intersectobjects (Scene.children,true);
Building the first Ray, unlike the previous line, where the ray is a mathematical ray, it is not an object and cannot be rendered. Because it is not a sub-object of any object, Raycaster's endpoint position takes world coordinates instead of relative coordinates, noting the difference between the end of the line segment at the same position as before.
Because we use a sub-object, the second argument of intersectobjects must be set to true to force the check of each sub-object, otherwise raycaster will only check the object of the first parameter and ignore the Globemesh.
1 if(Intersects.length > 0 ) {2 varflag_safe=0;//it should be possible to dispense with this variable3 //Enron walks through the following cycle to explain that there is no other object in the collision zone4 for(vari=0;i<intersects.length;i++)5 {6 //The specified collision must be visible, must have a face, must not be the original object, must be within the collision detection range (in fact, because the ray through the sub-object results of uncertainty)7 if(Intersects[i].object.visible && intersects[i].face&& ( This. Object3d.inter_group!=intersects[i].object.inter_group) &&intersects[i].distance< This. Object3d.inter_length) {8 9 varintersected =Intersects[i];Ten This. UpdateLine2 ( This. Line3.uuid,NewThree. Vector3 (0,0,0), Intersected.point.clone (). Sub ( This. PlanetGroup.position.clone (). Add ( This. object3d.position)), 0xff0000);//Collision Detection Line
As mentioned above, Raycaster cannot detect the inner surface of an object, but when it comes to detection of a sub-object, the proposition becomes uncertain, so add more judgment conditions (this is not self-pit yourself ...). )
1 varRaycaster2=NewThree. Raycaster (Intersected.point, This. Vector3.clone (). Negate (). normalize ());//The ray bounces back when it crosses the object .2Raycaster2.far= This. object3d.inter_length;3 varIntersects2 = Raycaster2.intersectobjects (Scene.children,true);4 //Now that you have encountered another object, you must reflect back to the original object to ensure that it does not collide (the case that bounces back to the other side of the object is removed by the collision boundary value)5 if(Intersects2.length > 0 )6 {7Flag_safe=1;8 for(varj=0;j<intersects2.length;j++)9 {Ten if(Intersects2[j].object.visible && intersects2[j].face&& (intersected.object.inter_group!= Intersects2[j].object.inter_group) &&intersects2[j].distance< This. Object3d.inter_length) One { A if(intersects2[j].object.inter_group== This. Object3d.inter_group)The//inter_group property is the same,returned the original object - { -flag_safe=0;//no collisions occurred the } - Break; - } - } + if(flag_safe==1) - { + This. Flag_coll = 1; A } at}
The logic here is not elegant enough to adjust it next time.
Iv. Direction of optimization:
1, the current "3D collision detection" to achieve the simplest case of collision detection, but the algorithm still has great limitations, such as this case, collision detection Ray can never pass through other objects:
The solution I think of is:
The Raycaster is extended to detect the edge collisions of objects by expanding the number of parallel rays in the direction of detection, which requires the knowledge of linear algebra and needs to be reviewed.
2, in the absence of the setting of translucent, may occur objects overlap but did not judge the situation, the suspicion is because I use the "First collision detection" method, three.js that the overlapping parts of the entity does not need to be drawn automatically discarded, resulting in a ray detection is not overlapping parts.
V. Expansion:
Yesterday's three.js example of American veteran Lee Stemkoski shows another method of collision detection, with advantages and disadvantages compared to my approach.
Demo Address: http://stemkoski.github.io/Three.js/Collision-Detection.html
Core code:
1 for(varVertexindex = 0; Vertexindex < MovingCube.geometry.vertices.length; vertexindex++)2 { 3 varLocalvertex =Movingcube.geometry.vertices[vertexindex].clone ();4 varGlobalvertex =localvertex.applymatrix4 (Movingcube.matrix);5 varDirectionvector =globalvertex.sub (movingcube.position);6 7 varRay =Newthree. Raycaster (Originpoint, Directionvector.clone (). normalize ());8 varCollisionresults =ray.intersectobjects (collidablemeshlist);9 if(Collisionresults.length > 0 && collisionresults[0].distance <directionvector.length ())TenAppendText ("hit"); One}
This method makes a collision detection Ray from the center of the object to each vertex of the object, and if the distance from the collision point of the first object to the center of the object is less than the distance from the center of the object to the vertex, a collision is considered.
Web3D Programming Summary--3d Collision detection