void GetInfoFromSelection() { //don't start looking for a color until we're done with our selection Transform rCanvas = App.ActiveCanvas.transform; if (!m_SelectionInfoQueryComplete && (m_SelectionObjectIndex >= rCanvas.childCount)) { int iBestObject = -1; float fBestDistance = 999999.0f; Vector3 vSelectionCenter = transform.position; float fSelectionRadius = GetSize(); for (int i = 0; i < m_CurrentSelection.Count; ++i) { //don't try to get info from complex objects SelectionObject rSelectedObject = m_CurrentSelection[i]; if (rSelectedObject.m_ComplexObject) { continue; } MeshFilter rMeshFilter = rSelectedObject.m_Object.GetComponent <MeshFilter>(); Vector3 vTransformedCenter = rSelectedObject.m_Object.transform.InverseTransformPoint(vSelectionCenter); //check each triangle for intersection int iMeshVertCount = rMeshFilter.mesh.vertexCount; Vector3[] aVerts = rMeshFilter.mesh.vertices; Vector3[] aNorms = rMeshFilter.mesh.normals; for (int j = 0; j < iMeshVertCount; j += 3) { //check to see if we're within the sphere radius to the plane of this triangle Vector3 vVert = aVerts[j]; Vector3 vNorm = aNorms[j]; float fDistToPlane = SignedDistancePlanePoint(ref vNorm, ref vVert, ref vTransformedCenter); float fAbsDistToPlane = Mathf.Abs(fDistToPlane); if (fAbsDistToPlane < fSelectionRadius && fAbsDistToPlane < fBestDistance) { //we're within the radius to this triangle's plane, find the projected point fDistToPlane *= -1.0f; Vector3 vPlaneOffsetVector = vNorm * fDistToPlane; Vector3 vPlaneIntersection = vTransformedCenter + vPlaneOffsetVector; Vector3 vVert2 = aVerts[i + 1]; Vector3 vVert3 = aVerts[i + 2]; //walk the projected point toward the triangle center Vector3 vTriCenter = (vVert + vVert2 + vVert3) * 0.33333f; Vector3 vToTriCenter = vTriCenter - vPlaneIntersection; float fWalkDistance = Mathf.Min(vToTriCenter.magnitude, fSelectionRadius); vToTriCenter.Normalize(); vToTriCenter *= fWalkDistance; vPlaneIntersection += vToTriCenter; //see if this projected point is in the triangle if (PointInTriangle(ref vPlaneIntersection, ref vVert, ref vVert2, ref vVert3)) { //our projected point is in this triangle, store this distance as the best iBestObject = i; fBestDistance = fDistToPlane; break; } } } } //this can happen if we don't have a selection if (iBestObject != -1) { BaseBrushScript rBrushScript = m_CurrentSelection[iBestObject].m_Object.GetComponent <BaseBrushScript>(); if (rBrushScript) { m_SelectionColor = rBrushScript.CurrentColor; m_SelectionBrush = rBrushScript.Descriptor; m_SelectionInfoValid = true; } } else { m_SelectionColor = Color.white; m_SelectionBrush = null; } m_SelectionInfoQueryComplete = true; } }
void UpdateSelection() { //0.1 ms float fTimeSlice = 1.0f / (10000.0f); int iTimeSliceInTicks = (int)(fTimeSlice * System.Diagnostics.Stopwatch.Frequency); Transform rCanvas = App.ActiveCanvas.transform; int iNumCanvasChildren = rCanvas.childCount; //reset selection if we've moved or adjusted our size float fSelectionRadius = GetSize(); Vector3 vSelectionCenter = transform.position; Vector3 vSelectionCenterMovement = vSelectionCenter - m_SelectionPositionPrev; float fSelectionRadiusDiff = m_SelectionRadiusPrev - fSelectionRadius; if (vSelectionCenterMovement.sqrMagnitude > 0.0001f || Mathf.Abs(fSelectionRadiusDiff) > 0.001f) { ResetSelection(); m_SelectionPositionPrev = vSelectionCenter; m_SelectionRadiusPrev = fSelectionRadius; } m_SelectionInfoQueryWasComplete = m_SelectionInfoQueryComplete; float fObjectProgressPercent = 0.0f; //DebugDrawBounds(); //early out if there's nothing to look at if (iNumCanvasChildren > 0 && m_SelectionObjectIndex < iNumCanvasChildren) { m_SelectionStopwatch.Reset(); m_SelectionStopwatch.Start(); bool bDone = false; bool bComplexModel = false; //spin until we've taken up too much time while (!bDone) { //check child bounds Transform rChild = rCanvas.GetChild(m_SelectionObjectIndex); if (rChild.gameObject.activeSelf) { bComplexModel = false; MeshFilter rMeshFilter = rChild.GetComponent <MeshFilter>(); if (rMeshFilter == null) { //look for a complex model ObjModelScript rModelScript = rChild.GetComponent <ObjModelScript>(); if (rModelScript) { if (m_SelectionObjectChildIndex < rModelScript.m_MeshChildren.Length) { rMeshFilter = rModelScript.m_MeshChildren[m_SelectionObjectChildIndex]; bComplexModel = true; } } } if (rMeshFilter) { Bounds rMeshBounds = rMeshFilter.mesh.bounds; rMeshBounds.Expand(fSelectionRadius); Vector3 vTransformedCenter = rChild.InverseTransformPoint(vSelectionCenter); if (rMeshBounds.Contains(vTransformedCenter)) { //bounds valid, check vert intersection with sphere int iMeshVertCount = rMeshFilter.mesh.vertexCount; Vector3[] aVerts = rMeshFilter.mesh.vertices; Vector3[] aNorms = rMeshFilter.mesh.normals; while (m_SelectionVertIndex < iMeshVertCount - 2) { //check to see if we're within the sphere radius to the plane of this triangle Vector3 vVert = aVerts[m_SelectionVertIndex]; Vector3 vNorm = aNorms[m_SelectionVertIndex]; float fDistToPlane = SignedDistancePlanePoint(ref vNorm, ref vVert, ref vTransformedCenter); if (Mathf.Abs(fDistToPlane) < fSelectionRadius) { //we're within the radius to this triangle's plane, find the projected point fDistToPlane *= -1.0f; Vector3 vPlaneOffsetVector = vNorm * fDistToPlane; Vector3 vPlaneIntersection = vTransformedCenter + vPlaneOffsetVector; Vector3 vVert2 = aVerts[m_SelectionVertIndex + 1]; Vector3 vVert3 = aVerts[m_SelectionVertIndex + 2]; //walk the projected point toward the triangle center Vector3 vTriCenter = (vVert + vVert2 + vVert3) * 0.33333f; Vector3 vToTriCenter = vTriCenter - vPlaneIntersection; float fWalkDistance = Mathf.Min(vToTriCenter.magnitude, fSelectionRadius); vToTriCenter.Normalize(); vToTriCenter *= fWalkDistance; vPlaneIntersection += vToTriCenter; //see if this projected point is in the triangle if (PointInTriangle(ref vPlaneIntersection, ref vVert, ref vVert2, ref vVert3)) { //selected! SelectionObject rNewSelectedObject = new SelectionObject(); rNewSelectedObject.m_Object = rChild.gameObject; rNewSelectedObject.m_ComplexObject = bComplexModel; m_CurrentSelection.Add(rNewSelectedObject); //this will guarantee we'll move on from this model, complex or not bComplexModel = false; break; } } //after each triangle, check our time m_SelectionVertIndex += 3; bDone = m_SelectionStopwatch.ElapsedTicks > iTimeSliceInTicks; if (bDone) { fObjectProgressPercent = (float)m_SelectionVertIndex / (float)iMeshVertCount; break; } } } } } //if we're not flagged as done, we just finished this object, so move on to the next if (!bDone) { //if we're looking at a complex model, look at the next piece of the model if (bComplexModel) { ++m_SelectionObjectChildIndex; } else { //move to the next object ++m_SelectionObjectIndex; m_SelectionObjectChildIndex = 0; } m_SelectionVertIndex = 0; if (m_SelectionObjectIndex >= iNumCanvasChildren) { //if we reached the end of the line, we're done break; } //might as well check per object bDone = m_SelectionStopwatch.ElapsedTicks > iTimeSliceInTicks; } } m_SelectionStopwatch.Stop(); } //set progress float fProgressInterval = 1.0f; if (iNumCanvasChildren > 0) { fProgressInterval /= (float)iNumCanvasChildren; } float fCanvasProgress = fProgressInterval * (float)m_SelectionObjectIndex; float fBrushProgress = fObjectProgressPercent * fProgressInterval; SetToolProgress(fCanvasProgress + fBrushProgress + 0.001f); }