| 173 | } |
| 174 | |
| 175 | SWresults ModelSurfaceWalker::Move(SurfaceWalker &sw, vec3 *points, const vec3 &dir, float drip_dist, std::vector<WalkLine> *trace) { |
| 176 | // Get transformed edges; |
| 177 | vec3 edges[3]; |
| 178 | edges[0] = points[1] - points[0]; |
| 179 | edges[1] = points[2] - points[1]; |
| 180 | edges[2] = points[0] - points[2]; |
| 181 | |
| 182 | // Use normal and first edge to construct local space |
| 183 | vec3 normal = normalize(cross(edges[0], edges[1])); |
| 184 | vec3 right = normalize(cross(normal, edges[0])); |
| 185 | vec3 up = normalize(edges[0]); |
| 186 | |
| 187 | // Convert points and edges to local space |
| 188 | vec2 points_local[3]; |
| 189 | for (unsigned i = 0; i < 3; ++i) { |
| 190 | vec3 temp = points[i] - points[0]; |
| 191 | points_local[i] = vec2(dot(temp, right), |
| 192 | dot(temp, up)); |
| 193 | } |
| 194 | vec2 edge_local[3]; |
| 195 | for (unsigned i = 0; i < 3; ++i) { |
| 196 | edge_local[i] = points_local[(i + 1) % 3] - points_local[i]; |
| 197 | } |
| 198 | |
| 199 | // Get inner edge normals |
| 200 | vec2 edge_local_normal[3]; |
| 201 | for (unsigned i = 0; i < 3; ++i) { |
| 202 | edge_local_normal[i] = vec2(edge_local[i][1], -edge_local[i][0]); |
| 203 | } |
| 204 | |
| 205 | // Calculate surface walker movement in local space |
| 206 | vec2 old_pos_local = sw.pos[1] * points_local[1] + |
| 207 | sw.pos[2] * points_local[2]; |
| 208 | vec2 dir_local = normalize(vec2(dot(dir, right), dot(dir, up))); |
| 209 | |
| 210 | // Are we exiting the edge we came in on? If so, run along edge instead |
| 211 | bool drip_down_edge = false; |
| 212 | if (sw.on_edge != -1 && |
| 213 | dot(dir_local, edge_local_normal[sw.on_edge]) <= 0.0f) { |
| 214 | vec2 normalized_edge = normalize(edge_local[sw.on_edge]); |
| 215 | dir_local = normalized_edge * dot(normalized_edge, dir_local); |
| 216 | drip_down_edge = true; |
| 217 | // printf("Drip down edge\n"); |
| 218 | } |
| 219 | |
| 220 | // Predict drip position |
| 221 | vec2 new_pos_local = old_pos_local + dir_local * drip_dist; |
| 222 | |
| 223 | // Check for edge intersections |
| 224 | bool edge_intersected[3] = {false, false, false}; |
| 225 | float edge_intersect_time[3]; |
| 226 | for (unsigned i = 0; i < 3; ++i) { |
| 227 | if (dot(dir_local, edge_local_normal[i]) >= 0.0f) { |
| 228 | continue; |
| 229 | } |
| 230 | bool valid = line_intersect_2d(old_pos_local, |
| 231 | new_pos_local, |
| 232 | points_local[i], |
no test coverage detected