no_alias float BTri::getDistance(const vec3 &pos) const { int k = 2; for (int i = 0; i < 3; i++){ float d = planeDistance(edgePlanes[i], pos); if (d < 0){ // Project onto the line between the points vec3 dir = v[i] - v[k]; float c = dot(dir, pos - v[k]) / dot(dir, dir); vec3 d; if (c >= 1){ d = v[i]; } else { d = v[k]; if (c > 0) d += c * dir; } return length(pos - d); } k = i; } return fabsf(planeDistance(plane, pos)); }
no_alias bool BTri::isAbove(const vec3 &pos) const { /* return (edgeNormals[0].x * pos.x + edgeNormals[0].y * pos.y + edgeNormals[0].z * pos.z >= edgeOffsets[0] && edgeNormals[1].x * pos.x + edgeNormals[1].y * pos.y + edgeNormals[1].z * pos.z >= edgeOffsets[1] && edgeNormals[2].x * pos.x + edgeNormals[2].y * pos.y + edgeNormals[2].z * pos.z >= edgeOffsets[2]); */ /* return (edgePlanes[0].x * pos.x + edgePlanes[0].y * pos.y + edgePlanes[0].z * pos.z >= -edgePlanes[0].w && edgePlanes[1].x * pos.x + edgePlanes[1].y * pos.y + edgePlanes[1].z * pos.z >= -edgePlanes[1].w && edgePlanes[2].x * pos.x + edgePlanes[2].y * pos.y + edgePlanes[2].z * pos.z >= -edgePlanes[2].w); */ return (planeDistance(edgePlanes[0], pos) >= 0 && planeDistance(edgePlanes[1], pos) >= 0 && planeDistance(edgePlanes[2], pos) >= 0); }
no_alias vec3 planeHit(const vec3 &v0, const vec3 &v1, const vec4 &plane){ vec3 dir = v1 - v0; float d = planeDistance(plane, v0); vec3 pos = v0 - (d / dot((vec3 &) plane, dir)) * dir; return pos; }
no_alias bool BTri::intersects(const vec3 &v0, const vec3 &v1) const { vec3 dir = v0 - v1; // float k = (dot(normal, v0) + offset) / dot(normal, dir); float k = planeDistance(plane, v0) / dot(plane.xyz(), dir); if (k < 0 || k > 1) return false; vec3 pos = v0 - k * dir; for (unsigned int i = 0; i < 3; i++){ if (planeDistance(edgePlanes[i], pos) < 0){ // if (dot(edgeNormals[i], pos) < edgeOffsets[i]){ return false; } } return true; }
inline void findRoads(const Sequence &s) { unsigned int curr, currLink, next; unsigned int roadStart, roadStartLink; double d, hMax, length; bool lowSlope, roadOn = 0; curr = s.m_head; currLink = s.m_headLink; for (; curr != s.m_tail; s.next(curr, currLink)) { next = s.m_graphHolder->getNode(curr).getLink(currLink).getNext(); d = planeDistance(*s.m_graphHolder->getNode(curr), *s.m_graphHolder->getNode(next)); lowSlope = fabs(s.m_graphHolder->getNode(curr).getLink(currLink)->getSlope()) < roadsMaxSlope ? 1 : 0; // Entering event in a *possibile* road axis if (!roadOn && lowSlope) { length = 0; hMax = s.m_graphHolder->getNode(curr)->z; roadStart = curr; roadStartLink = currLink; } // Exit event from a """ else if (roadOn && !lowSlope && (length > hMax)) // Then sign ROAD the sequence from roadStart to curr. for (; roadStart != curr; s.next(roadStart, roadStartLink)) s.m_graphHolder->node(roadStart) .link(roadStartLink) ->setAttribute(SkeletonArc::ROAD); // Now update vars if (lowSlope) { length += d; if (hMax < s.m_graphHolder->getNode(next)->z) hMax = s.m_graphHolder->getNode(next)->z; } roadOn = lowSlope; } // At sequence end, force an exit event if (roadOn && (length > hMax)) for (; roadStart != curr; s.next(roadStart, roadStartLink)) s.m_graphHolder->node(roadStart) .link(roadStartLink) ->setAttribute(SkeletonArc::ROAD); }
no_alias void BNode::getDistance(const vec3 &pos, float &minDist) const { float d = planeDistance(tri.plane, pos); float dist = tri.getDistance(pos); if (dist < minDist){ minDist = dist; } if (back && d < minDist){ back->getDistance(pos, minDist); } if (front && -d < minDist){ front->getDistance(pos, minDist); } }
no_alias bool BNode::pushSphere(vec3 &pos, const float radius) const { float d = planeDistance(tri.plane, pos); bool pushed = false; if (fabsf(d) < radius){ if (tri.isAbove(pos)){ // pos += (radius - d) * tri.normal; pos += (radius - d) * tri.plane.xyz(); pushed = true; } } if (front != NULL && d > -radius) pushed |= front->pushSphere(pos, radius); if (back != NULL && d < radius) pushed |= back ->pushSphere(pos, radius); return pushed; }
no_alias bool BSP::isInOpenSpace(const vec3 &pos) const { if (top != NULL){ BNode *node = top; while (true){ float d = planeDistance(node->tri.plane, pos); if (d > 0){ if (node->front){ node = node->front; } else return true; } else { if (node->back){ node = node->back; } else return false; } } } return false; }
void BNode::build(Array <BTri> &tris, const int splitCost, const int balCost, const float epsilon){ uint index = 0; int minScore = 0x7FFFFFFF; for (uint i = 0; i < tris.getCount(); i++){ int score = 0; int diff = 0; for (uint k = 0; k < tris.getCount(); k++){ uint neg = 0, pos = 0; for (uint j = 0; j < 3; j++){ float dist = planeDistance(tris[i].plane, tris[k].v[j]); if (dist < -epsilon) neg++; else if (dist > epsilon) pos++; } if (pos){ if (neg) score += splitCost; else diff++; } else { if (neg) diff--; else diff++; } } score += balCost * abs(diff); if (score < minScore){ minScore = score; index = i; } } tri = tris[index]; tris.fastRemove(index); Array <BTri> backTris; Array <BTri> frontTris; for (uint i = 0; i < tris.getCount(); i++){ uint neg = 0, pos = 0; for (uint j = 0; j < 3; j++){ float dist = planeDistance(tri.plane, tris[i].v[j]); if (dist < -epsilon) neg++; else if (dist > epsilon) pos++; } if (neg){ if (pos){ BTri newTris[3]; int nPos, nNeg; tris[i].split(newTris, nPos, nNeg, tri.plane, epsilon); for (int i = 0; i < nPos; i++){ frontTris.add(newTris[i]); } for (int i = 0; i < nNeg; i++){ backTris.add(newTris[nPos + i]); } } else { backTris.add(tris[i]); } } else { frontTris.add(tris[i]); } } tris.reset(); if (backTris.getCount() > 0){ back = new BNode; back->build(backTris, splitCost, balCost, epsilon); } else back = NULL; if (frontTris.getCount() > 0){ front = new BNode; front->build(frontTris, splitCost, balCost, epsilon); } else front = NULL; }
void BTri::split(BTri *dest, int &nPos, int &nNeg, const vec4 &plane, const float epsilon) const { float d[3]; for (int i = 0; i < 3; i++){ d[i] = planeDistance(plane, v[i]); } int first = 2; int second = 0; while (!(d[second] > epsilon && d[first] <= epsilon)){ first = second; second++; } // Positive triangles nPos = 0; vec3 h = planeHit(v[first], v[second], plane); do { first = second; second++; if (second >= 3) second = 0; dest->v[0] = h; dest->v[1] = v[first]; if (d[second] > epsilon){ dest->v[2] = v[second]; } else { dest->v[2] = h = planeHit(v[first], v[second], plane); } dest->data = data; dest->finalize(); dest++; nPos++; } while (d[second] > epsilon); // Skip zero area triangle if (fabsf(d[second]) <= epsilon){ first = second; second++; if (second >= 3) second = 0; } // Negative triangles nNeg = 0; do { first = second; second++; if (second >= 3) second = 0; dest->v[0] = h; dest->v[1] = v[first]; if (d[second] < -epsilon){ dest->v[2] = v[second]; } else { dest->v[2] = planeHit(v[first], v[second], plane); } dest->data = data; dest->finalize(); dest++; nNeg++; } while (d[second] < -epsilon); }
no_alias BTri *BNode::intersectsCached(const vec3 &v0, const vec3 &v1, const vec3 &dir) const { #if 0 float d0 = planeDistance(tri.plane, v0); float d1 = planeDistance(tri.plane, v1); vec3 pos; if (d0 > 0){ if (d1 <= 0){ pos = v0 - (d0 / dot((vec3 &) tri.plane, dir)) * dir; } if (front != NULL){ BTri *tri; if (d1 <= 0){ tri = front->intersectsCached(v0, pos, dir); } else { tri = front->intersectsCached(v0, v1, dir); } if (tri) return tri; } if (d1 <= 0){ if (tri.isAbove(pos)) return (BTri *) &tri; if (back != NULL){ BTri *tri = back->intersectsCached(pos, v1, dir); if (tri) return tri; } } } else { if (d1 > 0){ pos = v0 - (d0 / dot((vec3 &) tri.plane, dir)) * dir; } if (back != NULL){ BTri *tri; if (d1 > 0){ tri = back->intersectsCached(v0, pos, dir); } else { tri = back->intersectsCached(v0, v1, dir); } if (tri) return tri; } if (d1 > 0){ if (tri.isAbove(pos)) return (BTri *) &tri; if (front != NULL){ BTri *tri = front->intersectsCached(pos, v1, dir); if (tri) return tri; } } } #else float d = planeDistance(tri.plane, v0); if (d > 0){ if (front != NULL){ BTri *tri = front->intersectsCached(v0, v1, dir); if (tri) return tri; } if (planeDistance(tri.plane, v1) < 0){ vec3 pos = v0 - (d / dot(tri.plane.xyz(), dir)) * dir; if (tri.isAbove(pos)) return (BTri *) &tri; if (back != NULL){ BTri *tri = back->intersectsCached(v0, v1, dir); if (tri) return tri; } } } else { if (back != NULL){ BTri *tri = back->intersectsCached(v0, v1, dir); if (tri) return tri; } if (planeDistance(tri.plane, v1) > 0){ vec3 pos = v0 - (d / dot(tri.plane.xyz(), dir)) * dir; if (tri.isAbove(pos)) return (BTri *) &tri; if (front != NULL){ BTri *tri = front->intersectsCached(v0, v1, dir); if (tri) return tri; } } } #endif return NULL; }
no_alias bool BNode::intersects(const vec3 &v0, const vec3 &v1, const vec3 &dir, vec3 *point, const BTri **triangle) const { #if 0 float d0 = planeDistance(tri.plane, v0); float d1 = planeDistance(tri.plane, v1); vec3 pos; if (d0 > 0){ if (d1 <= 0){ pos = v0 - (d0 / dot(tri.plane.xyz(), dir)) * dir; } if (front != NULL && front->intersects(v0, (d1 <= 0)? pos : v1, dir, point, triangle)) return true; if (d1 <= 0){ if (tri.isAbove(pos)){ if (point) *point = pos; if (triangle) *triangle = &tri; return true; } if (back != NULL && back->intersects(pos, v1, dir, point, triangle)) return true; } } else { if (d1 > 0){ pos = v0 - (d0 / dot(tri.plane.xyz(), dir)) * dir; } if (back != NULL && back->intersects(v0, (d1 > 0)? pos : v1, dir, point, triangle)) return true; if (d1 > 0){ if (tri.isAbove(pos)){ if (point) *point = pos; if (triangle) *triangle = &tri; return true; } if (front != NULL && front->intersects(pos, v1, dir, point, triangle)) return true; } } #else float d = planeDistance(tri.plane, v0); if (d > 0){ if (front != NULL && front->intersects(v0, v1, dir, point, triangle)) return true; if (planeDistance(tri.plane, v1) < 0){ vec3 pos = v0 - (d / dot(tri.plane.xyz(), dir)) * dir; if (tri.isAbove(pos)){ if (point) *point = pos; if (triangle) *triangle = &tri; return true; } if (back != NULL && back->intersects(v0, v1, dir, point, triangle)) return true; } } else { if (back != NULL && back->intersects(v0, v1, dir, point, triangle)) return true; if (planeDistance(tri.plane, v1) > 0){ vec3 pos = v0 - (d / dot(tri.plane.xyz(), dir)) * dir; if (tri.isAbove(pos)){ if (point) *point = pos; if (triangle) *triangle = &tri; return true; } if (front != NULL && front->intersects(v0, v1, dir, point, triangle)) return true; } } #endif return false; }
void renderDrawVoxel(Voxel *voxel, int frustCull, Vector center, float size, unsigned short maxDrawDepth) { int i; float distance; if (frustCull) { int count = 0; for (i = 0; i < 6; i++) { distance = planeDistance(renderEnv.scene.camera.frustrum[5 - i], center); if (distance < -size) { return; } if (distance >= size) { count++; } } if (count == 6) { frustCull = 0; } } else { distance = planeDistance(renderEnv.scene.camera.frustrum[0], center); } unsigned short depth = voxelGetDepth(voxel); if (depth == VOXEL_DISPLAY_VOXEL_DEPTH) { // This should be moved to a background thread ... or something similar. if (voxelIsDisplayUpdateRequired(voxel)) { voxelUpdateDisplay( voxel, center, size, maxDrawDepth ); } i = 0; if (distance > renderEnv.highMediumDetailBorder * renderEnv.scene.camera.farDist) { i++; if (distance > renderEnv.mediumLowDetailBorder * renderEnv.scene.camera.farDist) { i++; } } glCallList(voxelGetDisplayList(voxel) + i); } else if (depth < VOXEL_DISPLAY_VOXEL_DEPTH) { float half = size / 2.0f; float quarter = size / 4.0f; for (i = 0; i < voxel->childCount; i++) { switch (voxelGetPosition(voxel->children[i])) { case 0: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x - quarter, center.y - quarter, center.z - quarter), half, maxDrawDepth); break; case 1: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x - quarter, center.y - quarter, center.z + quarter), half, maxDrawDepth); break; case 2: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x - quarter, center.y + quarter, center.z - quarter), half, maxDrawDepth); break; case 3: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x - quarter, center.y + quarter, center.z + quarter), half, maxDrawDepth); break; case 4: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x + quarter, center.y - quarter, center.z - quarter), half, maxDrawDepth); break; case 5: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x + quarter, center.y - quarter, center.z + quarter), half, maxDrawDepth); break; case 6: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x + quarter, center.y + quarter, center.z - quarter), half, maxDrawDepth); break; case 7: renderDrawVoxel(voxel->children[i], frustCull, vectorLiteral(center.x + quarter, center.y + quarter, center.z + quarter), half, maxDrawDepth); break; default: break; } } } }