Example #1
0
std::vector<double> TEvent::GetPerpFoot(std::vector<double> referencePosition) {
  /**
   * create dropped perpendicular foot (perpFoot) first
   * g: S = position_ + t * eventDirection
   * t = <referencePosition - position_, eventDirection>
   *     / <eventDirection, eventDirection>
   */
  std::vector<double> eventDirection, difference, perpFoot;
  // create directional vector out of angles
  eventDirection.push_back(cos(azimuthalAngle_) * sin(polarAngle_));
  eventDirection.push_back(sin(azimuthalAngle_) * sin(polarAngle_));
  eventDirection.push_back(cos(polarAngle_));
  // create difference vector between sensorPosition and this event
  for (int i = 0; i < 3; ++i) {
      difference.push_back(referencePosition.at(i) - position_.at(i));
  }
  // calculate gradient of straight line
  double t = GetInnerProduct(difference, eventDirection)
           / GetInnerProduct(eventDirection, eventDirection);
  // calculate dropped perpendicular foot using the straight line equation g
  for (int i = 0; i < 3; ++i) {
      perpFoot.push_back(position_.at(i) + t * eventDirection.at(i));
  }

  return perpFoot;
}
Example #2
0
//---------------------------------------------------------------------------
//  CalculateTangent()
//     Calculate a tangent vector from positions, normals and coordinates.
//     位置・法線・UV座標から接線ベクトルを計算する
//---------------------------------------------------------------------------
void CalculateTangent(const MQPoint& v0, const MQPoint& v1, const MQPoint& v2,
		const MQPoint& n0, const MQPoint& n1, const MQPoint& n2,
		const MQCoordinate& t0, const MQCoordinate& t1, const MQCoordinate& t2,
		MQPoint& tan0, MQPoint& tan1, MQPoint& tan2)
{
	MQPoint edge1, edge2, crossP;

	edge1.x = v1.x - v0.x;
	edge1.y = t1.u - t0.u; // s-vector - don't need to compute this multiple times
	edge1.z = t1.v - t0.v; // t-vector
	edge2.x = v2.x - v0.x;
	edge2.y = t2.u - t0.u; // another s-vector
	edge2.z = t2.v - t0.v; // another t-vector
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	float tanX = -crossP.y / crossP.x;
	tan0.x = tanX;
	tan1.x = tanX;
	tan2.x = tanX;

	// y, s, t
	edge1.x = v1.y - v0.y;
	edge2.x = v2.y - v0.y;
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	float tanY = -crossP.y / crossP.x;
	tan0.y = tanY;
	tan1.y = tanY;
	tan2.y = tanY;

	// z, s, t
	edge1.x = v1.z - v0.z;
	edge2.x = v2.z - v0.z;
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	float tanZ = -crossP.y / crossP.x;
	tan0.z = tanZ;
	tan1.z = tanZ;
	tan2.z = tanZ;

	// Orthonormalize to normal
	tan0 -= n0 * GetInnerProduct(tan0, n0);
	tan1 -= n1 * GetInnerProduct(tan1, n1);
	tan2 -= n2 * GetInnerProduct(tan2, n2);

	// Normalize tangents
	tan0 = Normalize(tan0);
	tan1 = Normalize(tan1);
	tan2 = Normalize(tan2);
}
Example #3
0
double TEvent::GetDistance(std::vector<double> firstPosition,
                           std::vector<double> secondPosition) {
  std::vector<double> difference;
  // create difference vector between firstPosition and secondPosition
  for (int i = 0; i < 3; i++) {
      difference.push_back(secondPosition.at(i) - firstPosition.at(i));
  }
  // return distance
  return sqrt(GetInnerProduct(difference, difference));
}
Example #4
0
//---------------------------------------------------------------------------
//  GetQuadNormal()
//     Get a normal vector for a face constituted by four points.
//     4点からなる面の法線を得る
//---------------------------------------------------------------------------
MQPoint GetQuadNormal(const MQPoint& p0, const MQPoint& p1, const MQPoint& p2, const MQPoint& p3)
{
	MQPoint n,n1a,n1b,n2a,n2b;

	n1a = GetNormal(p0, p1, p2);
	n1b = GetNormal(p0, p2, p3);
	n2a = GetNormal(p1, p2, p3);
	n2b = GetNormal(p1, p3, p0);

	// 凹型や歪んだ四角形の場合は片方の内積が小さくなるので、
	// 2法線の内積の値を比較して、大きい方を選ぶ
	if(GetInnerProduct(n1a,n1b) > GetInnerProduct(n2a,n2b)) {
		n = Normalize(n1a + n1b);
	} else {
		n = Normalize(n2a + n2b);
	}

	return n;
}
Example #5
0
float GetTriangleArea(const MQCoordinate& p1, const MQCoordinate& p2, const MQCoordinate& p3)
{
	MQCoordinate v1,v2;
	float d1,d2,t,u;

	v1=p2-p1; d1=GetSize(v1);
	v2=p3-p1; d2=GetSize(v2);
	t = d1*d2;
	if(t == 0) return 0;
	u = (GetInnerProduct(v1,v2) / t);
	return t * (1 - u*u);
}
Example #6
0
//---------------------------------------------------------------------------
//  GetTriangleArea()
//     Get an area of a triangle constituted by three points
//     3点からなる三角形の面積を得る
//---------------------------------------------------------------------------
float GetTriangleArea(const MQPoint& p1, const MQPoint& p2, const MQPoint& p3)
{
	MQPoint v1,v2;
	float d1,d2,t,u;

	v1=p2-p1; d1=v1.abs();
	v2=p3-p1; d2=v2.abs();
	t = d1*d2;
	if(t == 0) return 0;
	u = (GetInnerProduct(v1,v2) / t);
	return t * (1 - u*u);
}
Example #7
0
float GetCrossingAngle(const MQCoordinate& v1, const MQCoordinate& v2)
{
	float d,c;

	d = GetSize(v1) * GetSize(v2);
	if(d == 0.0f)
		return 0.0f;

	c = GetInnerProduct(v1, v2) / d;
	if(c >= 1.0f) return 0.0f;
	if(c <=-1.0f) return PI;

	return acosf(c);
}
Example #8
0
MQObjNormal::MQObjNormal(MQObject obj)
{
	int i,j;
	int face_count, vert_count;
	int vi[4];

	face_count = obj->GetFaceCount();
	vert_count = obj->GetVertexCount();

	MQPoint *face_n = new MQPoint[face_count];
	normal = new MQPoint[face_count * 4];

	// 面ごとに法線を計算
	for(i=0; i<face_count; i++)
	{
		int count = obj->GetFacePointCount(i);

		// 三角形と四角形では面に対する法線の計算法は異なる
		switch(count) {
		case 3:
			obj->GetFacePointArray(i, vi);
			face_n[i] = GetNormal(
				obj->GetVertex(vi[0]), obj->GetVertex(vi[1]), obj->GetVertex(vi[2]));
			break;
		case 4:
			obj->GetFacePointArray(i, vi);
			face_n[i] = GetQuadNormal(
				obj->GetVertex(vi[0]), obj->GetVertex(vi[1]), 
				obj->GetVertex(vi[2]), obj->GetVertex(vi[3]));
			break;
		default:
			face_n[i].zero();
			break;
		}
	}

	switch(obj->GetShading()) {
	case MQOBJECT_SHADE_FLAT:
		for(i=0; i<face_count; i++)
		{
			int count = obj->GetFacePointCount(i);
			for(j=0; j<count; j++)
				normal[i*4+j] = face_n[i];
			for(; j<4; j++)
				normal[i*4+j].zero();
		}
		break;

	case MQOBJECT_SHADE_GOURAUD:
		{
			MQGouraudHashTable *vtbl, *cvt;
			MQGouraudHash *hash, *chs;

			// スムージング角度の取得
			float facet = cosf( RAD(obj->GetSmoothAngle()) );

			// ハッシュの初期化
			vtbl = new MQGouraudHashTable[face_count];
			hash = new MQGouraudHash[vert_count + face_count*4];
			int hash_count = vert_count;

			// 面ごとにハッシュに法線ベクトルをセット
			for(i=0,cvt=vtbl; i<face_count; i++,cvt++)
			{
				int count = obj->GetFacePointCount(i);
				if(count < 3) continue;

				obj->GetFacePointArray(i, vi);

				// 面中の各頂点ごとに法線ベクトルをハッシュへ格納してやる
				for(j=0; j<count; j++)
				{
					// 注目する頂点に対してのハッシュを得る
					chs = &hash[vi[j]];

					// ハッシュがまだ空ならそこに情報を格納
					if(chs->count == 0) {
						chs->nv = face_n[i];
						chs->count++;
						(*cvt)[j] = chs;
						continue;
					}

					// ハッシュが空でないなら、既に格納されている法線とのスムージング
					// 角度をチェックする必要がある。
					// アルゴリズムとしては不完全かもしれないが、とりあえず実用程度に
					// はなると思う。

					const MQPoint& pa = face_n[i];
					float da = pa.norm();
					for(; ; chs=chs->next)
					{
						// 2面の角度をチェック
						float c = 0.0f;
						if(da > 0.0f) {
							MQPoint& pb = chs->nv;
							float db = pb.norm();
							if(db > 0.0f)
								c = GetInnerProduct(pa, pb) / sqrtf(da*db);
						}
							
						// スムージング角度以内か?
						if(c >= facet)
						{
							// 注目する頂点に対して面の法線ベクトルをそのまま加算する。
							// 本来なら、注目する頂点に属する面内の2辺の角度によって
							// ベクトルの加算量を変えるべきだが、とりあえずパス。
							chs->nv += pa;
							chs->count++;
							(*cvt)[j] = chs;
							break;
						}

						// スムージングは行われないので、次のハッシュをチェック。
						// 次のハッシュデータがない場合は新規作成。
						if(chs->next == NULL) {
							(*cvt)[j] = chs->next = &hash[hash_count++];
							chs = chs->next;
							chs->nv = pa;
							chs->count = 1;
							chs->next = NULL;
							break;
						}
					}
				}
			}

			// ハッシュ中の法線ベクトルの正規化
			for(i=0,chs=hash; i<hash_count; i++,chs++) {
				if(chs->count > 1)
					chs->nv.normalize();
			}

			// 法線をバッファにセット
			for(i=0,cvt=vtbl; i<face_count; i++,cvt++)
			{
				int count = obj->GetFacePointCount(i);
				if(count < 3) continue;
				for(j=0; j<count; j++)
					normal[i*4+j] = (*cvt)[j]->nv;
				for(; j<4; j++)
					normal[i*4+j].zero();
			}

			// ハッシュを解放
			delete[] vtbl;
			delete[] hash;
		}
		break;
	}

	delete[] face_n;
}