/// <summary> /// 頂点情報配列から実際にメッシュとして使えるデータに変換する。 /// </summary> protected static ClassBox.Figure CreateFigureData(ClassBox.Vertex[] positions) { //頂点座標配列の下準備 int polyNum = positions.Length - 2; //生成物が何角形か Vector3[] vertices = new Vector3[positions.Length]; //頂点の数と同じ int[] triangles = new int[polyNum * 3 * 2]; //何角形 * 3 * 2(両面) //頂点座標とテクスチャ座標の設定 for (int i = 0; i < vertices.Length; i++) { vertices[i] = positions[i].vertex; } for (int polyIndex = 0; polyIndex < polyNum; polyIndex++) { int index = -1; //一番遠い頂点の番号を記憶する int next = 0, prev = 0; //前後の点 float aDis = 0f; //一番遠い頂点までの距離を記憶する for (int i = 0; i < positions.Length; i++) { if (positions[i].flagActive) { float bDis = Vector3.Distance(Vector3.zero, positions[i].vertex); //Debug.Log("Distance : " + i + " : "+ bDis); if (bDis > aDis) { aDis = bDis; index = i; } } } //前後の点との外積の向きを記録しておく FuncBox.FindNextPrevPoint(index, positions, out next, out prev); Vector3 nextVector, prevVector; //indexから見たnextとprevのベクトルから外積を求める nextVector = positions[next].vertex - positions[index].vertex; prevVector = positions[prev].vertex - positions[index].vertex; Vector3 crossDirection; //外積 crossDirection = Vector3.Cross(nextVector, prevVector); //外積を求める //ループカウンタ(無限ループに陥る可能性があるので) int loopCounter = 0; //適した頂点が見つかるまで繰り返す while (true) { //Debug.Log("index is " + index); //頂点と二辺のなす角が180°未満か確かめる //前後の頂点の番号を求める FuncBox.FindNextPrevPoint(index, positions, out next, out prev); //Debug.Log("next : " + next + " prev : " + prev); //一番離れている点 = 180°以内なので意味ない?↓ /* * //前後の頂点が判明したのでなす角を求める * //前後の頂点との角度を求めた差が角度になる(内積を使ってもいいみたいだが、180°以上の角になる場合向きが必要なので今回は不採用) * float angle = 0f, pAngle = 0f, nAngle = 0f; * //Vector3のAngle関数を使うより自分でAtan2を使って角度を求めるほうが早い(1/2 ~ 2/3早い程度)し何故か正確 * pAngle = TwoPointAngleD(positions[prev].vertex, positions[index].vertex); * nAngle = TwoPointAngleD(positions[next].vertex, positions[index].vertex); * * angle = Mathf.Abs(nAngle - pAngle); * * Debug.Log("nextAngle : " + nAngle + " prevAngle : " + pAngle + " Angle : " + angle); * * //180°以上の場合より離れている点が存在しているので他の点を探す(おそらくありえない ← ありえました!!!!!!!!) * if(angle >= 180) { * Debug.Log("もっと遠い点があるよ!"); * //インデックスをずらす * index = next; * }*/ //ちょうどいい点とは、三点の外積の向きと三点がつくる三角形の中に他の頂点が入っていない場合 bool flagVertex = true; //ちょうどいい点かどうか //前後と座標のなす三角形の中に他の頂点がかぶっていないか確認する for (int i = 0; i < positions.Length; i++) { if (i != prev && i != index && i != next) { if (positions[i].flagActive) { if (FuncBox.PointOnTriangle(positions[prev].vertex, positions[index].vertex, positions[next].vertex, positions[i].vertex)) { //Debug.Log("三角形にかぶっている点があるので再探索します。"); flagVertex = false; break; } } } } //三点の外積を求める Vector3 nextVec, prevVec; //indexから見たnextとprevのベクトルから外積を求める nextVec = positions[next].vertex - positions[index].vertex; prevVec = positions[prev].vertex - positions[index].vertex; Vector3 crossDir; //外積 crossDir = Vector3.Cross(nextVec, prevVec); //外積を求める //外積の向きを比較する if (!FuncBox.CrossDirection(crossDirection, crossDir)) { //Debug.Log("外積の向きが異なります!"); flagVertex = false; } if (flagVertex) { //ちょうど良い点だった場合 //trianglesに頂点を設定し //indexの頂点のflagActiveをfalseにする //Debug.Log("ちょうどいい点が見つかりました。"); //うまく表示されない場合はここの頂点指定が逆になっているかも //時計回りと反時計回りの二回分登録する(両面) triangles[polyIndex * 6 + 0] = next; triangles[polyIndex * 6 + 1] = index; triangles[polyIndex * 6 + 2] = prev; triangles[polyIndex * 6 + 3] = prev; triangles[polyIndex * 6 + 4] = index; triangles[polyIndex * 6 + 5] = next; positions[index].flagActive = false; break; } else { //駄目な点だった場合 //indexをずらす index = next; } //ループカウンタ loopCounter++; //強制的にループを抜ける if (loopCounter > positions.Length) { loopCounter = 0; //Debug.Log("無限ループに陥る可能性があったので処理を中断しました。"); polyIndex = polyNum; break; } } } ClassBox.Figure figure = new ClassBox.Figure(positions, triangles, Color.black); return(figure); }
/// <summary> /// 作成に必要な情報を付加した頂点リストを返す。 /// </summary> protected static ClassBox.Vertex[] CreateVertices(Vector3[] posList) { var vertices = new List <ClassBox.Vertex>(); //角度 //まずは一番遠い頂点の外積の向きを求める int index = -1; //一番遠い頂点の番号 float aDis = 0f; //一番遠い頂点までの距離を記憶する for (int i = 0; i < posList.Length; i++) { float bDis = Vector3.Distance(Vector3.zero, posList[i]); //Debug.Log("Distance : " + i + " : "+ bDis); if (bDis > aDis) { aDis = bDis; index = i; } } //前後の点を見つける int next, prev; FuncBox.FindNextPrevPoint(index, posList, out next, out prev); //外積を求める Vector3 nextVector, prevVector; //indexから見たnextとprevのベクトルから外積を求める nextVector = posList[next] - posList[index]; prevVector = posList[prev] - posList[index]; Vector3 crossDirection; //内向き(0~180)の外積 crossDirection = Vector3.Cross(nextVector, prevVector); //外積を求める //頂点を順に調べて角度を求める for (int i = 0; i < posList.Length; i++) { FuncBox.FindNextPrevPoint(i, posList, out next, out prev); //ベクトルを求める nextVector = posList[next] - posList[i]; prevVector = posList[prev] - posList[i]; //外積を求める Vector3 crossDir; //外積 crossDir = Vector3.Cross(nextVector, prevVector); //外積を求める //内積から角度を求める //まず距離 float nextVecDis = Vector3.Distance(posList[next], posList[i]); float prevVecDis = Vector3.Distance(posList[prev], posList[i]); //角度 float cosS = Vector3.Dot(nextVector, prevVector) / (nextVecDis * prevVecDis); float radian = Mathf.Acos(cosS); float degree = radian * Mathf.Rad2Deg; //角度が180°の場合頂点として成り立たないので弾く if (degree != 180) { ////外積の向きが異なる場合360°から引く if (!FuncBox.CrossDirection(crossDirection, crossDir)) { //Debug.Log("外積の向きが異なっています"); degree = 360 - degree; } Debug.Log("Angle : " + i + " : " + degree); //情報格納 vertices.Add(new ClassBox.Vertex(posList[i], degree)); } } return(vertices.ToArray()); }