BOOL Bounds::LineIntersection(const Vect &v1, const Vect &v2, float &fT) const { float tMax = M_INFINITE; float tMin = -M_INFINITE; Vect rayVect = (v2-v1); float rayLength = rayVect.Len(); Vect rayDir = rayVect*(1.0f/rayLength); Vect center = GetCenter(); Vect E = Max-center; Vect T = center-v1; for(int i=0; i<3; i++) { float e = T.ptr[i]; float f = rayDir.ptr[i]; float fI = 1.0f/f; if(fabs(f) > 0.0f) { float t1 = (e+E.ptr[i])*fI; float t2 = (e-E.ptr[i])*fI; if(t1 > t2) { if(t2 > tMin) tMin = t2; if(t1 < tMax) tMax = t1; } else { if(t1 > tMin) tMin = t1; if(t2 < tMax) tMax = t2; } if(tMin > tMax) return FALSE; if(tMax < 0.0f) return FALSE; } else if( ((-e - E.ptr[i]) > 0.0f) || ((-e + E.ptr[i]) < 0.0f) ) { return FALSE; } if(tMin > rayLength) return FALSE; } if(tMin > 0.0f) { fT = (tMin/rayLength); return TRUE; } else { fT = (tMax/rayLength); return TRUE; } }
BOOL PointOnFiniteLine(const Vect &lineV1, const Vect &lineV2, const Vect &p) { Vect line = lineV2-lineV1; float lineDist = line.Len(); Plane plane; plane.Dir = line*(1.0f/lineDist); plane.Dist = plane.Dir.Dot(lineV1); float dist = p.DistFromPlane(plane); if((dist < 0.0f) || (dist > lineDist)) return FALSE; float fT = (dist/lineDist); return p.CloseTo(Lerp(lineV1, lineV2, fT)); }
//vector version void CalcTorque(Vect &val1, const Vect &val2, float torque, float minAdjust, float fT) { if(val1 == val2) return; Vect line = (val2-val1); float origDist = line.Len(); Vect dir = line * (1.0f/origDist); float torqueDist = origDist*torque; //uses distance to determine torque speed float adjustDist = torqueDist*fT; if(torqueDist < minAdjust) torqueDist = minAdjust; //prevents torque from going too slow if(adjustDist <= (origDist-LARGE_EPSILON)) val1 += dir*adjustDist; //adds toque to val1 else val1 = val2; //sets val1 to val2 if overshot with the minimum torque value }
Vect CartToPolar(const Vect &cart) { Vect polar; polar.z = cart.Len(); if(CloseFloat(polar.z, 0.0f, EPSILON)) { polar.x = 0.0f; polar.y = 0.0f; polar.z = 0.0f; } else { polar.x = asin(cart.y / polar.z); polar.y = atan2(cart.x, cart.z); } return polar; }
BOOL Plane::GetDoublePlaneIntersection(const Plane &p2, Vect &intOrigin, Vect &intDir) const { float fCosAngle = (Dir|p2.Dir); float fSinAngle = sqrt(1.0f-(fCosAngle*fCosAngle)); if(fabs(fSinAngle) < LARGE_EPSILON) return FALSE; float fInvSinAngle = 1.0f/fSinAngle; float fChi1 = (Dist-(fCosAngle*p2.Dist))*fInvSinAngle; float fChi2 = (p2.Dist-(fCosAngle*Dist))*fInvSinAngle; intDir = Dir^p2.Dir; float iLen = 1.0f/intDir.Len(); intDir *= iLen; intOrigin = (Dir*fChi1) + (p2.Dir*fChi2); intOrigin *= iLen; return TRUE; }
void RotationManipulator::ProcessMouseRay(const Vect &cameraDir, float scale, const Vect &rayOrig, const Vect &rayDir) { traceIn(RotationManipulator::ProcessMouseRay); activeAxis = -1; curCameraDir = cameraDir; Matrix mat; mat.SetIdentity(); mat.Translate(GetWorldPos()); mat.Scale(scale, scale, scale); bManipulating = false; DWORD i,j; for(i=0; i<3; i++) { for(j=0; j<30; j++) { DWORD jp1 = (j == 29) ? 0 : j+1; Vect norm = axisNorms[i][j]; if(norm.Dot(cameraDir) > 0.01f) continue; Vect v1 = axisLines[i][j]; Vect v2 = axisLines[i][jp1]; v1.TransformPoint(mat); v2.TransformPoint(mat); Vect lineVec = (v2-v1); float lineLen = lineVec.Len(); Vect lineDir = lineVec*(1.0f/lineLen); float fT1, fT2; if(ClosestLinePoints(rayOrig, rayDir, v1, lineDir, fT1, fT2)) { if((fT2 < 0.0f) || (fT2 > lineLen)) continue; Vect closestPoint1 = rayOrig+(rayDir*fT1); Vect closestPoint2 = v1+(lineDir*fT2); if(closestPoint1.Dist(closestPoint2) < (0.4f*scale)) { Vect axis(0.0f, 0.0f, 0.0f); axis.ptr[i] = 1.0f; activeAxis = i; clickDir = cameraDir.Cross(axis.Cross(norm)).Cross(cameraDir).Norm(); clickOrig = closestPoint1; bManipulating = true; return; } } } } mat.SetIdentity(); mat.Translate(GetWorldPos()); mat.Rotate(Quat().SetLookDirection(cameraDir)); mat.Scale(scale*1.25f, scale*1.25f, scale*1.25f); for(j=0; j<30; j++) { DWORD jp1 = (j == 29) ? 0 : j+1; Vect norm = axisNorms[2][j]; Vect v1 = axisLines[2][j]; Vect v2 = axisLines[2][jp1]; v1.TransformPoint(mat); v2.TransformPoint(mat); norm.TransformVector(mat); Vect lineVec = (v2-v1); float lineLen = lineVec.Len(); Vect lineDir = lineVec*(1.0f/lineLen); float fT1, fT2; if(ClosestLinePoints(rayOrig, rayDir, v1, lineDir, fT1, fT2)) { if((fT2 < 0.0f) || (fT2 > lineLen)) continue; Vect closestPoint1 = rayOrig+(rayDir*fT1); Vect closestPoint2 = v1+(lineDir*fT2); if(closestPoint1.Dist(closestPoint2) < (0.6f*scale)) { activeAxis = 4; clickDir = cameraDir.Cross(norm); clickOrig = closestPoint1; curCameraDir = cameraDir; bManipulating = true; return; } } } traceOut; }
void EditorMesh::BuildLightmapUVs(float maxAngle, float adjVal, int seperationUnits) { Vect maxSize = bounds.Max-bounds.Min; //adjVal *= MAX(maxSize.x, MAX(maxSize.y, maxSize.z)); adjVal *= bounds.GetDiamater(); int i, j; MakePolyEdges(); maxAngle = cosf(RAD(maxAngle)); BitList ProcessedPolys, ProcessedEdges, ProcessedVerts; List<UINT> UnprocessedPolys; ProcessedPolys.SetSize(PolyList.Num()); ProcessedEdges.SetSize(PolyEdgeList.Num()); ProcessedVerts.SetSize(VertList.Num()); UnprocessedPolys.SetSize(PolyList.Num()); for(i=0; i<UnprocessedPolys.Num(); i++) UnprocessedPolys[i] = i; List<UVSection> Sections; BitList SplitVerts; SplitVerts.SetSize(VertList.Num()); //go through each polygon and find neighboring polygons while(UnprocessedPolys.Num()) { UINT curPoly = UnprocessedPolys[0]; List<UINT> SectionPolys; UVSection §ion = *Sections.CreateNew(); section.mapDir = GetPolyDir(curPoly); List<Vect> PolyLines; // calling this recursively will build us up a section based upon this poly AddLMPolyInfo info(curPoly, maxAngle, section.mapDir, SectionPolys, PolyLines, UnprocessedPolys, ProcessedPolys, ProcessedEdges); AddLightmapUVPoly(info); section.mapDir.Norm(); //find best mapping direction Vect XDir, YDir; BitList addedLines; addedLines.SetSize(PolyLines.Num()); float bestLength = 0.0f; Vect bestDir; for(i=0; i<PolyLines.Num(); i++) { if(addedLines[i]) continue; addedLines.Set(i); Vect &line1 = PolyLines[i]; Vect line1Norm = (line1 + (section.mapDir * -section.mapDir.Dot(line1))).Norm(); Vect lineTotal = line1; for(j=i+1; j<PolyLines.Num(); j++) { if(addedLines[j]) continue; Vect &line2 = PolyLines[j]; Vect line2Norm = (line2 + (section.mapDir * -section.mapDir.Dot(line2))).Norm(); if(line1Norm.Dot(line2Norm) > 0.9f) //about 10 degrees { lineTotal += line2; addedLines.Set(j); } } float length = lineTotal.Len(); if(length > bestLength) { bestDir = lineTotal.Norm(); bestLength = length; } } if(section.mapDir.CloseTo(bestDir) || (-section.mapDir).CloseTo(bestDir)) { if(bestDir.x > bestDir.y) { if(bestDir.x > bestDir.z) *(DWORD*)&bestDir.x |= 0x80000000; else *(DWORD*)&bestDir.z |= 0x80000000; } else { if(bestDir.y > bestDir.z) *(DWORD*)&bestDir.y |= 0x80000000; else *(DWORD*)&bestDir.z |= 0x80000000; } } YDir = bestDir.Cross(section.mapDir).Norm(); XDir = YDir.Cross(section.mapDir).Norm(); /*if(section.mapDir.GetAbs().CloseTo(Vect(0.0f, 1.0f, 0.0f))) { float fOne = (*(DWORD*)§ion.mapDir.y & 0x80000000) ? -1.0f : 1.0f; XDir.Set(fOne, 0.0f, 0.0f); YDir.Set(0.0f, 0.0f, fOne); } else { XDir = Vect(0.0f, 1.0f, 0.0f).Cross(section.mapDir).Norm(); YDir = XDir.Cross(section.mapDir).Norm(); }*/ float top, bottom, left, right; //project UVs onto this section for(i=0; i<SectionPolys.Num(); i++) { PolyFace &poly = PolyList[SectionPolys[i]]; for(j=0; j<poly.Faces.Num(); j++) { UINT faceID = poly.Faces[j]; Face &f = FaceList[faceID]; section.Faces << faceID; for(int k=0; k<3; k++) { UINT vert = f.ptr[k]; Vect &v = VertList[vert]; Vect2 uv; uv.x = XDir.Dot(v); uv.y = YDir.Dot(v); if(!section.ProjectedVerts.Num()) { left = right = uv.x; top = bottom = uv.y; } else { if(uv.x < left) left = uv.x; else if(uv.x > right) right = uv.x; if(uv.y < top) top = uv.y; else if(uv.y > bottom) bottom = uv.y; } section.Verts << vert; section.ProjectedVerts << uv; } } } section.width = (right-left)+(adjVal*2.0f); section.height = (bottom-top)+(adjVal*2.0f); for(i=0; i<section.Verts.Num(); i++) { section.ProjectedVerts[i].x -= left-adjVal; section.ProjectedVerts[i].y -= top-adjVal; } //find any verts that might need splitting section.SplitVerts.SetSize(section.Verts.Num()); for(i=0; i<section.Verts.Num(); i++) { BOOL bFoundVert = FALSE; UINT vert = section.Verts[i]; if(SplitVerts[vert]) bFoundVert = TRUE; else { for(j=0; j<Sections.Num()-1; j++) { UVSection &prevSection = Sections[j]; if(prevSection.Verts.HasValue(vert)) { SplitVerts.Set(vert); bFoundVert = TRUE; break; } } } if(bFoundVert) section.SplitVerts.Set(i); } } //split verts where the lightmap coordinates are for(i=1; i<Sections.Num(); i++) { UVSection §ion = Sections[i]; for(j=0; j<section.SplitVerts.Num(); j++) { if(section.SplitVerts[j]) { UINT faceID = j/3; UINT faceVert = j%3; UINT vertID = section.Verts[j]; UINT newVertID = VertList.Num(); Face &f = FaceList[faceID]; f.ptr[faceVert] = newVertID; VertList.Add(VertList[vertID]); UVList.Add(UVList[vertID]); NormalList.Add(NormalList[vertID]); if(TangentList.Num()) TangentList.Add(TangentList[vertID]); } } } LMUVList.SetSize(VertList.Num()); //find the most optimal way to put sections together BestStorageInfo info(Sections, seperationUnits); FindBestUVStorage(info); float curSizeI = 1.0f/MAX(info.curSize.x, info.curSize.y); for(i=0; i<info.CurStorage.Num(); i++) { StorageData &data = info.CurStorage[i]; UVSection §ion = Sections[data.item]; for(j=0; j<section.Verts.Num(); j++) { UINT vertID = section.Verts[j]; if(ProcessedVerts[vertID]) continue; Vect2 &v = section.ProjectedVerts[j]; Vect2 newPos; if(data.bRot) { newPos.x = section.height-v.y; newPos.y = v.x; } else newPos = v; LMUVList[vertID] = (data.pos+newPos)*curSizeI; ProcessedVerts.Set(vertID); } } //free data for(i=0; i<Sections.Num(); i++) Sections[i].FreeData(); Sections.Clear(); FreePolyEdges(); }