1 /**
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008, Luke Benstead.
  4  All rights reserved.
  5 
  6  Redistribution and use in source and binary forms, with or without modification,
  7  are permitted provided that the following conditions are met:
  8 
  9  Redistributions of source code must retain the above copyright notice,
 10  this list of conditions and the following disclaimer.
 11  Redistributions in binary form must reproduce the above copyright notice,
 12  this list of conditions and the following disclaimer in the documentation
 13  and/or other materials provided with the distribution.
 14 
 15  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 16  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 17  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 18  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 19  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 20  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 21  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 22  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 24  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 25  */
 26 
 27 cc.kmRay2 = function(start, dir){
 28   this.start = start || new cc.kmVec2();
 29     this.start = start || new cc.kmVec2();
 30 };
 31 
 32 cc.kmRay2Fill = function(ray, px, py,vx,vy){
 33     ray.start.x = px;
 34     ray.start.y = py;
 35     ray.dir.x = vx;
 36     ray.dir.y = vy;
 37 };
 38 
 39 cc.kmRay2IntersectLineSegment = function(ray, p1, p2, intersection){
 40     var x1 = ray.start.x;
 41     var y1 = ray.start.y;
 42     var x2 = ray.start.x + ray.dir.x;
 43     var y2 = ray.start.y + ray.dir.y;
 44     var x3 = p1.x;
 45     var y3 = p1.y;
 46     var x4 = p2.x;
 47     var y4 = p2.y;
 48 
 49     var denom = (y4 -y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
 50     var ua, x, y;
 51     //If denom is zero, the lines are parallel
 52     if(denom > -cc.kmEpsilon && denom < cc.kmEpsilon) {
 53         return cc.KM_FALSE;
 54     }
 55 
 56     ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
 57 //    var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
 58 
 59     x = x1 + ua * (x2 - x1);
 60     y = y1 + ua * (y2 - y1);
 61 
 62     if(x < cc.kmMin(p1.x, p2.x) - cc.kmEpsilon ||
 63         x > cc.kmMax(p1.x, p2.x) + cc.kmEpsilon ||
 64         y < cc.kmMin(p1.y, p2.y) - cc.kmEpsilon ||
 65         y > cc.kmMax(p1.y, p2.y) + cc.kmEpsilon) {
 66         //Outside of line
 67         //printf("Outside of line, %f %f (%f %f)(%f, %f)\n", x, y, p1.x, p1.y, p2.x, p2.y);
 68         return cc.KM_FALSE;
 69     }
 70 
 71     if(x < cc.kmMin(x1, x2) - cc.kmEpsilon ||
 72         x > cc.kmMax(x1, x2) + cc.kmEpsilon ||
 73         y < cc.kmMin(y1, y2) - cc.kmEpsilon ||
 74         y > cc.kmMax(y1, y2) + cc.kmEpsilon) {
 75         //printf("Outside of ray, %f %f (%f %f)(%f, %f)\n", x, y, x1, y1, x2, y2);
 76         return cc.KM_FALSE;
 77     }
 78 
 79     intersection.x = x;
 80     intersection.y = y;
 81 
 82     return cc.KM_TRUE;
 83 };
 84 
 85 cc.calculate_line_normal = function(p1, p2, normal_out){
 86     var tmp = new cc.kmVec2();
 87     cc.kmVec2Subtract(tmp, p2, p1); //Get direction vector
 88 
 89     normal_out.x = -tmp.y;
 90     normal_out.y = tmp.x;
 91     cc.kmVec2Normalize(normal_out, normal_out);
 92 
 93     //TODO: should check that the normal is pointing out of the triangle
 94 };
 95 
 96 cc.kmRay2IntersectTriangle = function(ray, p1, p2, p3, intersection, normal_out){
 97     var intersect = new cc.kmVec2();
 98     var final_intersect = new cc.kmVec2();
 99     var  normal = new cc.kmVec2();
100     var distance = 10000.0;
101     var intersected = cc.KM_FALSE;
102 
103     var tmp,this_distance;
104 
105     if(cc.kmRay2IntersectLineSegment(ray, p1, p2, intersect)) {
106         tmp = new cc.kmVec2();
107 
108         intersected = cc.KM_TRUE;
109         this_distance = cc.kmVec2Length(cc.kmVec2Subtract(tmp, intersect, ray.start));
110         if(this_distance < distance) {
111             final_intersect.x = intersect.x;
112             final_intersect.y = intersect.y;
113             distance = this_distance;
114 
115             cc.calculate_line_normal(p1, p2, normal);
116         }
117     }
118 
119     if(cc.kmRay2IntersectLineSegment(ray, p2, p3, intersect)) {
120         tmp = new cc.kmVec2();
121         intersected = cc.KM_TRUE;
122 
123         this_distance = cc.kmVec2Length(cc.kmVec2Subtract(tmp, intersect, ray.start));
124         if(this_distance < distance) {
125             final_intersect.x = intersect.x;
126             final_intersect.y = intersect.y;
127             distance = this_distance;
128 
129             cc.calculate_line_normal(p2, p3, normal);
130         }
131     }
132 
133     if(cc.kmRay2IntersectLineSegment(ray, p3, p1, intersect)) {
134         tmp = new cc.kmVec2();
135         intersected = cc.KM_TRUE;
136 
137         this_distance = cc.kmVec2Length(cc.kmVec2Subtract(tmp, intersect, ray.start));
138         if(this_distance < distance) {
139             final_intersect.x = intersect.x;
140             final_intersect.y = intersect.y;
141             distance = this_distance;
142 
143             cc.calculate_line_normal(p3, p1, normal);
144         }
145     }
146 
147     if(intersected) {
148         intersection.x = final_intersect.x;
149         intersection.y = final_intersect.y;
150         if(normal_out) {
151             normal_out.x = normal.x;
152             normal_out.y = normal.y;
153         }
154     }
155 
156     return intersected;
157 };
158 
159 cc.kmRay2IntersectCircle = function(ray, centre, radius, intersection) {
160     cc.log("cc.kmRay2IntersectCircle() has not been implemented.");
161 };