bool PhysicsMesh::LoadFrom(Mesh * mesh) { // Clear old triangles.ClearAndDelete(); quads.ClearAndDelete(); name = mesh->name; source = mesh->source; aabb = *mesh->aabb; for (int i = 0; i < mesh->numFaces; ++i) { // Just copy shit from it MeshFace * faces = &mesh->faces[i]; assert((faces->numVertices <= 4 || faces->numVertices >= 3) && "Bad vertices count in faces"); int vi0 = faces->vertices[0], vi1 = faces->vertices[1], vi2 = faces->vertices[2]; assert(vi0 < mesh->vertices.Size() && vi0 >= 0); Vector3f p1 = mesh->vertices[vi0], p2 = mesh->vertices[vi1], p3 = mesh->vertices[vi2]; if (faces->numVertices == 4){ Vector3f p4 = mesh->vertices[faces->vertices[3]]; Quad * quad = new Quad(); quad->Set4Points(p1, p2, p3, p4); quads.Add(quad); } else if (faces->numVertices == 3){ Triangle * tri = new Triangle(); tri->Set3Points(p1, p2, p3); triangles.Add(tri); } } if (quads.Size() == 0 && triangles.Size() == 0) assert(false && "Unable to load physicsmesh from mesh source!"); else std::cout<<"\nCreated physics mesh for \""<<source<<"\": "; if (triangles.Size()) std::cout<<"\n- "<<triangles.Size()<<" triangles"; if (quads.Size()) std::cout<<"\n- "<<quads.Size()<<" quads"; // Re-generate it. if (useCollisionShapeOctrees) GenerateCollisionShapeOctree(); return true; }
int CVFindQuads::Process(CVPipeline * pipe) { pipe->quads.Clear(); good = false; /// Check for ... in pipeline if (pipe->corners.size() == 0 && pipe->lines.Size() == 0) { errorString = "No corners or lines in pipeline."; return -1; } float minimumWidthSquared = minimumWidth->GetInt() * minimumWidth->GetInt(); // Line-style! if (pipe->lines.Size()) { int linesAtStart = pipe->lines.Size(); std::cout<<"\nLines: "<<linesAtStart; /// Then try to locate at least 2 lines that are parallel first? // Approximate, assume 2 horizontal lines, and pick those two which are extremes (highest and lowest). List<Line> singleLines; for (int i = 0; i < pipe->lines.Size(); ++i) { Line line = pipe->lines[i]; Line line2; bool foundPair = false; // Compare with list of lines. for (int j = 0; j < singleLines.Size(); ++j) { line2 = singleLines[j]; // Any suitable? // First check length. if (AbsoluteValue(line.Length() - line2.Length()) > maxLengthDiff->GetFloat()) continue; // Ensure both the start and end points are pretty parallel if (AbsoluteValue(line.start.x - line2.start.x) > maxCornerXDiff->GetFloat()) continue; if (AbsoluteValue(line.stop.x - line2.stop.x) > maxCornerXDiff->GetFloat()) continue; foundPair = true; break; } if (foundPair) { // Limit the range in X for both lines so that they work "together" (overlapping) #define Minimum(a,b) ( (a < b) ? a : b) #define Maximum(a,b) ( (a > b) ? a : b) Line min, max; if (line.start.y < line2.start.y){ min = line; max = line2; } else { min = line2; max = line; } min.stop.x = max.stop.x = Minimum(min.stop.x, max.stop.x); min.start.x = max.start.x = Maximum(min.start.x, max.start.x); // Create rectangle using these two lines! o-o Quad quad; quad.Set4Points(min.start, min.stop, max.stop, max.start); pipe->quads.Add(quad); good = true; } // If not, add this line to the list. else singleLines.Add(line); } } // Use corners if we have any. if (pipe->corners.size()){ // Constraint for now... if (pipe->corners.size() != 4){ errorString = "Skipping. Simple algorithm requires exactly 4 corners."; return -1; } // Look through all corners. Find the top 2 and bottom 2. List<cv::Point2f> sortedList, unsortedList; for (int i = 0; i < pipe->corners.size(); ++i) unsortedList.Add(pipe->corners[i]); /// Sort by Y-position. while (unsortedList.Size()) { cv::Point2f max = unsortedList[0]; int maxIndex = 0; for (int i = 1; i < unsortedList.Size(); ++i) { cv::Point2f point = pipe->corners[i]; if (point.y > max.y){ max = point; maxIndex = i; } } // Add the max to the sortedList and remove it from the list to be sorted. sortedList.Add(max); unsortedList.RemoveIndex(maxIndex); std::cout<<"\nAdded item"<<sortedList.Size()<<": "<<max; } /// Now, store top and bottom. List<cv::Point2f> top, bottom; top.Add(sortedList[0]); top.Add(sortedList[1]); bottom.Add(sortedList[2]); bottom.Add(sortedList[3]); #define ToVec3f(cvVec) (Vector3f(cvVec.x, cvVec.y, 0)) if (top[0].x < top[1].x) { topLeft = ToVec3f(top[0]); topRight = ToVec3f(top[1]); } else { topLeft = ToVec3f(top[1]); topRight = ToVec3f(top[0]); } if (bottom[0].x < bottom[1].x) { bottomLeft = ToVec3f(bottom[0]); bottomRight = ToVec3f(bottom[1]); } else { bottomLeft = ToVec3f(bottom[1]); bottomRight = ToVec3f(bottom[0]); } // Fetch vectors for lines between the top and bottom points. // From left to right. topLine = Vector2f(topRight.x - topLeft.x, topRight.y - topLeft.y); bottomLine = Vector2f(bottomRight.x - bottomLeft.x, bottomRight.y - bottomLeft.y); // Normalize them before dot-product topLine.Normalize(); bottomLine.Normalize(); // Check that they are parralel float dotProduct = topLine.DotProduct(bottomLine); if (AbsoluteValue(dotProduct) < 0.9f) { errorString = "Bottom and top lines not parralell enough."; return -1; } // Fetch vector between left top and left bottom. Vector2f topLeftToBottomLeft(bottomLeft.x - topLeft.x, bottomLeft.y - topLeft.y); // Check that it is perpendicular to either top or bottom lines. topLeftToBottomLeft.Normalize(); dotProduct = topLine.DotProduct(topLeftToBottomLeft); if (AbsoluteValue(dotProduct) > 0.1f) { errorString = "Left and top lines not perpendicular enough."; return -1; } // We have a quad if we reach here! Quad quad; quad.Set4Points(ToVec3f(bottomLeft), ToVec3f(bottomRight), ToVec3f(topRight), ToVec3f(topLeft)); pipe->quads.Add(quad); good = true; } returnType = CVReturnType::QUADS; return returnType; }