X operations(XOPS)に非常に近いFPSゲームを制作・リメイクし、成果物をオープンソースとして公開することを目的としたプロジェクトです。
修訂 | 93 (tree) |
---|---|
時間 | 2015-06-14 20:33:25 |
作者 | xops-mikan |
ブロックの法線ベクトル算出を変更、当たり判定に用いる関数のバグ修正
@@ -455,7 +455,7 @@ | ||
455 | 455 | speed = (float)sqrt(plist->move_x*plist->move_x + plist->move_y*plist->move_y + plist->move_z*plist->move_z); |
456 | 456 | |
457 | 457 | //最短距離の座標を求める |
458 | - min_dist = DistancePosRay(camera_x, camera_y, camera_z, plist->x, plist->y, plist->z, plist->move_x/speed, plist->move_y/speed, plist->move_z/speed, (float)speed*2); | |
458 | + min_dist = DistancePosRay(camera_x, camera_y, camera_z, plist->x, plist->y, plist->z, plist->move_x/speed, plist->move_y/speed, plist->move_z/speed); | |
459 | 459 | |
460 | 460 | //最短距離時の座標を求める |
461 | 461 | dist = (float)sqrt(dist2 - min_dist*min_dist); |
@@ -88,7 +88,7 @@ | ||
88 | 88 | bool CollideSphereRay(float s_x, float s_y, float s_z, float s_r, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float *Dist, float maxDist); |
89 | 89 | bool CollideAABBRay(float box_min_x, float box_min_y, float box_min_z, float box_max_x, float box_max_y, float box_max_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float *Dist, float maxDist); |
90 | 90 | bool CollideCylinderRay(float c_x, float c_y, float c_z, float c_r, float c_h, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float *Dist, float maxDist); |
91 | -float DistancePosRay(float Pos_x, float Pos_y, float Pos_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float maxDist); | |
91 | +float DistancePosRay(float Pos_x, float Pos_y, float Pos_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z); | |
92 | 92 | bool Collide2DLine(int A1x, int A1y, int A2x, int A2y, int B1x, int B1y, int B2x, int B2y, int *out_x, int *out_y); |
93 | 93 | bool Get2DLineInBox(int line_x1, int line_y1, int line_x2, int line_y2, int box_x1, int box_y1, int box_x2, int box_y2, int *out_line_x1, int *out_line_y1, int *out_line_x2, int *out_line_y2); |
94 | 94 |
@@ -177,6 +177,10 @@ | ||
177 | 177 | int uvID[4]; |
178 | 178 | float g; |
179 | 179 | float xs, ys, zs; |
180 | + float g1; | |
181 | + float xs1, ys1, zs1; | |
182 | + float g2; | |
183 | + float xs2, ys2, zs2; | |
180 | 184 | float lx, ly, lz; |
181 | 185 | float rx, ry, rz, a; |
182 | 186 |
@@ -193,18 +197,30 @@ | ||
193 | 197 | blockdataface(j, vID, uvID); |
194 | 198 | |
195 | 199 | //面の法線(ベクトル)と、その長さを求める |
196 | - xs = ((data[i].y[ vID[3] ] - data[i].y[ vID[2] ]) * (data[i].z[ vID[0] ] - data[i].z[ vID[2] ])) - ((data[i].y[ vID[0] ] - data[i].y[ vID[2] ]) * (data[i].z[ vID[3] ] - data[i].z[ vID[2] ])); | |
197 | - ys = ((data[i].z[ vID[3] ] - data[i].z[ vID[2] ]) * (data[i].x[ vID[0] ] - data[i].x[ vID[2] ])) - ((data[i].z[ vID[0] ] - data[i].z[ vID[2] ]) * (data[i].x[ vID[3] ] - data[i].x[ vID[2] ])); | |
198 | - zs = ((data[i].x[ vID[3] ] - data[i].x[ vID[2] ]) * (data[i].y[ vID[0] ] - data[i].y[ vID[2] ])) - ((data[i].x[ vID[0] ] - data[i].x[ vID[2] ]) * (data[i].y[ vID[3] ] - data[i].y[ vID[2] ])); | |
199 | - g = (float)sqrt(xs * xs + ys * ys + zs * zs); | |
200 | + xs1 = ((data[i].y[ vID[3] ] - data[i].y[ vID[2] ]) * (data[i].z[ vID[0] ] - data[i].z[ vID[2] ])) - ((data[i].y[ vID[0] ] - data[i].y[ vID[2] ]) * (data[i].z[ vID[3] ] - data[i].z[ vID[2] ])); | |
201 | + ys1 = ((data[i].z[ vID[3] ] - data[i].z[ vID[2] ]) * (data[i].x[ vID[0] ] - data[i].x[ vID[2] ])) - ((data[i].z[ vID[0] ] - data[i].z[ vID[2] ]) * (data[i].x[ vID[3] ] - data[i].x[ vID[2] ])); | |
202 | + zs1 = ((data[i].x[ vID[3] ] - data[i].x[ vID[2] ]) * (data[i].y[ vID[0] ] - data[i].y[ vID[2] ])) - ((data[i].x[ vID[0] ] - data[i].x[ vID[2] ]) * (data[i].y[ vID[3] ] - data[i].y[ vID[2] ])); | |
203 | + g1 = (float)sqrt(xs1 * xs1 + ys1 * ys1 + zs1 * zs1); | |
200 | 204 | |
201 | - //もし法線がおかしければ、もう一方の三角形で計算をやり直す | |
202 | - if( g < 0.01f ){ | |
203 | - xs = ((data[i].y[ vID[1] ] - data[i].y[ vID[0] ]) * (data[i].z[ vID[2] ] - data[i].z[ vID[0] ])) - ((data[i].y[ vID[2] ] - data[i].y[ vID[0] ]) * (data[i].z[ vID[1] ] - data[i].z[ vID[0] ])); | |
204 | - ys = ((data[i].z[ vID[1] ] - data[i].z[ vID[0] ]) * (data[i].x[ vID[2] ] - data[i].x[ vID[0] ])) - ((data[i].z[ vID[2] ] - data[i].z[ vID[0] ]) * (data[i].x[ vID[1] ] - data[i].x[ vID[0] ])); | |
205 | - zs = ((data[i].x[ vID[1] ] - data[i].x[ vID[0] ]) * (data[i].y[ vID[2] ] - data[i].y[ vID[0] ])) - ((data[i].x[ vID[2] ] - data[i].x[ vID[0] ]) * (data[i].y[ vID[1] ] - data[i].y[ vID[0] ])); | |
206 | - g = (float)sqrt(xs * xs + ys * ys + zs * zs); | |
205 | + //もう一方の三角形でも計算する | |
206 | + xs2 = ((data[i].y[ vID[1] ] - data[i].y[ vID[0] ]) * (data[i].z[ vID[2] ] - data[i].z[ vID[0] ])) - ((data[i].y[ vID[2] ] - data[i].y[ vID[0] ]) * (data[i].z[ vID[1] ] - data[i].z[ vID[0] ])); | |
207 | + ys2 = ((data[i].z[ vID[1] ] - data[i].z[ vID[0] ]) * (data[i].x[ vID[2] ] - data[i].x[ vID[0] ])) - ((data[i].z[ vID[2] ] - data[i].z[ vID[0] ]) * (data[i].x[ vID[1] ] - data[i].x[ vID[0] ])); | |
208 | + zs2 = ((data[i].x[ vID[1] ] - data[i].x[ vID[0] ]) * (data[i].y[ vID[2] ] - data[i].y[ vID[0] ])) - ((data[i].x[ vID[2] ] - data[i].x[ vID[0] ]) * (data[i].y[ vID[1] ] - data[i].y[ vID[0] ])); | |
209 | + g2 = (float)sqrt(xs2 * xs2 + ys2 * ys2 + zs2 * zs2); | |
210 | + | |
211 | + //正しい計算結果を採用する | |
212 | + if( g1 > g2 ){ | |
213 | + xs = xs1; | |
214 | + ys = ys1; | |
215 | + zs = zs1; | |
216 | + g = g1; | |
207 | 217 | } |
218 | + else{ | |
219 | + xs = xs2; | |
220 | + ys = ys2; | |
221 | + zs = zs2; | |
222 | + g = g2; | |
223 | + } | |
208 | 224 | |
209 | 225 | //法線(ベクトル)を正規化 |
210 | 226 | data[i].material[j].vx = xs / g; |
@@ -956,7 +956,7 @@ | ||
956 | 956 | } |
957 | 957 | |
958 | 958 | //点(球体の中心)とレイの最短距離を求める |
959 | - MinDist = DistancePosRay(s_x, s_y, s_z, RayPos_x, RayPos_y, RayPos_z, RayDir_x, RayDir_y, RayDir_z, maxDist); | |
959 | + MinDist = DistancePosRay(s_x, s_y, s_z, RayPos_x, RayPos_y, RayPos_z, RayDir_x, RayDir_y, RayDir_z); | |
960 | 960 | |
961 | 961 | if( MinDist <= s_r ){ |
962 | 962 | RayDist = sqrt(d*d - MinDist*MinDist); //(レイ始点から)点に最も近づく距離 |
@@ -1135,7 +1135,7 @@ | ||
1135 | 1135 | d = sqrt(x*x + z*z); |
1136 | 1136 | |
1137 | 1137 | //点(円柱の中心)とレイの最短距離を求める |
1138 | - cMinDist = DistancePosRay(c_x, 0.0f, c_z, RayPos_x, 0.0f, RayPos_z, RayDir_x, 0.0f, RayDir_z, maxDist); | |
1138 | + cMinDist = DistancePosRay(c_x, 0.0f, c_z, RayPos_x, 0.0f, RayPos_z, RayDir_x, 0.0f, RayDir_z); | |
1139 | 1139 | |
1140 | 1140 | //最短距離が半径より離れている時点で当たらない |
1141 | 1141 | if( cMinDist > c_r ){ |
@@ -1231,28 +1231,37 @@ | ||
1231 | 1231 | //! @param RayDir_x レイのベクトルを指定する X成分 |
1232 | 1232 | //! @param RayDir_y レイのベクトルを指定する Y成分 |
1233 | 1233 | //! @param RayDir_z レイのベクトルを指定する Z成分 |
1234 | -//! @param maxDist 判定を行う最大距離 | |
1235 | 1234 | //! @return 最短距離 |
1236 | 1235 | //! @warning RayPos(始点)と RayDir(ベクトル)を間違えないこと。 |
1237 | -float DistancePosRay(float Pos_x, float Pos_y, float Pos_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z, float maxDist) | |
1236 | +//! @attention レイの方向は考慮されますが、レイの長さは考慮されません。 | |
1237 | +float DistancePosRay(float Pos_x, float Pos_y, float Pos_z, float RayPos_x, float RayPos_y, float RayPos_z, float RayDir_x, float RayDir_y, float RayDir_z) | |
1238 | 1238 | { |
1239 | 1239 | float x1, y1, z1; |
1240 | 1240 | float x2, y2, z2; |
1241 | 1241 | float x3, y3, z3; |
1242 | + float Dot; | |
1242 | 1243 | |
1243 | 1244 | x1 = Pos_x - RayPos_x; |
1244 | 1245 | y1 = Pos_y - RayPos_y; |
1245 | 1246 | z1 = Pos_z - RayPos_z; |
1246 | - x2 = RayDir_x * maxDist; | |
1247 | - y2 = RayDir_y * maxDist; | |
1248 | - z2 = RayDir_z * maxDist; | |
1247 | + x2 = RayDir_x; | |
1248 | + y2 = RayDir_y; | |
1249 | + z2 = RayDir_z; | |
1249 | 1250 | |
1251 | + //内積 | |
1252 | + Dot = x1 * x2 + y1 * y2 + z1 * z2; | |
1253 | + | |
1254 | + //レイのベクトルが逆方向なら | |
1255 | + if( Dot < 0.0f ){ | |
1256 | + return sqrt(x1*x1 + y1*y1 + z1*z1); | |
1257 | + } | |
1258 | + | |
1250 | 1259 | //外積 |
1251 | 1260 | x3 = y1 * z2 - z1 * y2; |
1252 | 1261 | y3 = z1 * x2 - x1 * z2; |
1253 | 1262 | z3 = x1 * y2 - y1 * x2; |
1254 | 1263 | |
1255 | - return sqrt(x3*x3 + y3*y3 + z3*z3) / maxDist; | |
1264 | + return sqrt(x3*x3 + y3*y3 + z3*z3) / sqrt(RayDir_x*RayDir_x + RayDir_y*RayDir_y + RayDir_z*RayDir_z); | |
1256 | 1265 | } |
1257 | 1266 | |
1258 | 1267 | //! @brief 線分と線分の当たり判定(2D) |