Beispiel #1
0
// `計算點光源, 它和頂點位置, 頂點面向, 光源位置有關.`
void CalculatePointLight(Vertex_VCN *pVertices, int num_vertices)
{
	for ( int i=0; i<num_vertices; i++ )
	{
		// `求出轉換後在世界座標系的頂點位置`
		Vector4 vPosition = pVertices[i].m_Position * g_world_matrix;
		// `求出轉換後在世界座標系的頂點面向, RotateVector函式只做旋轉, 忽略位移.`
		Vector4 vNormal = g_world_matrix.RotateVector(pVertices[i].m_Normal);
		// `計算出頂點位置到光源的方向跟長度`
		Vector4 vVertex_to_Light = g_vLightPosition - vPosition; 
		float light_distance = vVertex_to_Light.NormalizeAndGetLength();
		// `vDistance用來計算光線隨距離衰減公式中1/(a*1 + b*d + c*d^2)分母的(1, d, d^2)`
		Vector4 vDistance(1.0f, light_distance, light_distance * light_distance);
		// `g_vLightAttenuation里記錄了計算衰減公式1/(a + b*d + c*d^2)里的(a,b,c)`
		// `Vector3Dot(vDistance, g_vLightAttenuation) = (a,b,c) dot (1,d,d^2) = (a + b*d + c*d^2)`
		Vector4 vAttenuation = Vector3Dot(vDistance, g_vLightAttenuation);
		// `頂點面向跟光線方向的交角, 決定反射光的強度.`
		Vector4 vIntensity = Vector3Dot(vNormal, vVertex_to_Light);
		// `把intensity局限在永遠大於0的范圍`
		vIntensity.Clamp_to_0();
		// `累加上隨距離衰減的光線強度`
		pVertices[i].m_Color += vIntensity * g_vLightColor / vAttenuation;
		pVertices[i].m_Color.Clamp_to_1();
	}
}
Beispiel #2
0
// `計算點光源, 它和頂點位置, 頂點面向, 光源位置, 光源方向, 光柱交角有關.`
void CalculateSpotLight(Vertex_VCN *pVertices, int num_vertices)
{
	float fSpotLightCutoffCos = FastMath::Cos( FastMath::DegreeToRadian(g_fSpotLightCutoff) );

	for ( int i=0; i<num_vertices; i++ )
	{
		// `求出轉換後在世界座標系的頂點位置`
		Vector4 vPosition = pVertices[i].m_Position * g_world_matrix;
		// `求出轉換後在世界座標系的頂點面向, RotateVector函式只做旋轉, 忽略位移.`
		Vector4 vNormal = g_world_matrix.RotateVector(pVertices[i].m_Normal);
		// `計算出頂點位置到光源的方向跟長度`
		Vector4 vVertex_to_Light = g_vLightPosition - vPosition; 
		float light_distance = vVertex_to_Light.NormalizeAndGetLength();
		// `頂點面向跟光線方向的交角, 可以決定反射光的強度.`
		Vector4 vCosine = Vector3Dot(g_vLightDirection, vVertex_to_Light);
		// `把vCosine局限在永遠大於0的范圍`
		vCosine.Clamp_to_0();
		float fCosine = vCosine.GetX();
		if ( fCosine >= fSpotLightCutoffCos )
		{
			// `頂點跟光線的交角小於fSpotightCutoffCos時, 才落在光柱范圍內.`
			Vector4 vDistance(1.0f, light_distance, light_distance * light_distance);
			// `g_vLightAttenuation里記錄了計算衰減公式1/(a + b*d + c*d^2)里的(a,b,c)`
			// `Vector3Dot(vDistance, g_vLightAttenuation) = (a,b,c) dot (1,d,d^2) = (a + b*d + c*d^2)`
			Vector4 vAttenuation = Vector3Dot(vDistance, g_vLightAttenuation);
			// `比較靠近光柱外圍部分的頂點, 光線會衰減.`
			float fFalloff = pow(fCosine, g_fSpotLightExponent);
			Vector4 vIntensity = Vector3Dot(vNormal, vVertex_to_Light);
			pVertices[i].m_Color += fFalloff * vIntensity * g_vLightColor / vAttenuation;
			pVertices[i].m_Color.Clamp_to_1();
		}
	}
}
Beispiel #3
0
	bool	Collision::GetReflectFloor( const float& height, Vector3& pos, Vector3& vec, float rate )
	{
		Vector3 p = pos;
		Vector3 v = vec;
		Vector3 n = Vector3( 0.0f, 1.0f, 0.0f );
		Vector3 out;
		float dist = 50.0f;

		float length = height - pos.y;
  		if ( length > 5.0f )	return false;

		// 移動量の長さ
		float vec_len = vec.Length();

		if ( vec_len > length )
		{
			// 法線正規化
			n.Normalize();

			// 入射ベクトルを法線に射影
			float dot = Vector3Dot( -vec, n );
			// 入射ベクトルと反射ベクトルの
			// 合成ベクトルから
			// 入射ベクトルを引く。
			vec = n*2.0f*dot - ( -vec );
			// 反射率の計算
			vec *= rate;
			return true;
		}
		return false;
	}
Beispiel #4
0
	//	オブジェクトの反射(固定)
	bool	Collision::GetRefrectFix( iexMesh* org, Vector3& pos, Vector3& vec, float rate )
	{
		Vector3 p = pos;
		Vector3 v = vec;
		Vector3 out;
		float dist = 50.0f;
		org->Update();

		if ( org->RayPick( &out, &p, &v, &dist ) == -1 )
			return false;
		// 移動量の長さ
		float vec_len = vec.Length();
		// 壁までのベクトル
		Vector3 pos_out_vec = out - pos;
		// 壁までの距離
		float pos_out_len = pos_out_vec.Length();
		if ( vec_len > pos_out_len )
		{
			// 法線正規化
			v.Normalize();
			// 入射ベクトルを法線に射影
			float dot = Vector3Dot( -vec, v );
			// 入射ベクトルと反射ベクトルの
			// 合成ベクトルから
			// 入射ベクトルを引く。
			vec = v*2.0f*dot - ( -vec );
			// 反射率の計算
			vec *= rate;
			return true;
		}
		return false;
	}
Beispiel #5
0
	// 線分と線分の距離の平方を返す(カプセル用)
	float	Collision::DistanceSegmentSegmentSq( const Vector3& l1p1, const Vector3& l1p2, const Vector3& l2p1, const Vector3& l2p2 )
	{
		// ねじれの位置の判定
		Vector3 v1 = l1p2 - l1p1;
		Vector3 v2 = l2p2 - l2p1;
		Vector3 n;
		Vector3Cross( n, v1, v2 );
		float nn = n.LengthSq();
		if ( nn ) {
			// 平行ではない
			Vector3 v12 = l2p1 - l1p1;
			float nv12 = Vector3Dot( n, v12 );
			Vector3 vd = n * ( nv12 / nn );
			Vector3 q1 = l2p1 - vd;
			Vector3 q2 = l2p2 - vd;
			Vector3 p1q1 = q1 - l1p1;
			Vector3 p1q2 = q2 - l1p1;
			Vector3 r1, r2;
			Vector3Cross( r1, v1, p1q1 );
			Vector3Cross( r2, v1, p1q2 );
			if ( Vector3Dot( r1, r2 ) < 0 ) {
				Vector3 v3 = q2 - q1;
				Vector3 q1p1 = l1p1 - q1;
				Vector3 q1p2 = l1p2 - q1;
				Vector3Cross( r1, v3, q1p1 );
				Vector3Cross( r2, v3, q1p2 );
				if (Vector3Dot( r1, r2 ) < 0 ) {
					// ねじれの位置
					return nv12 * nv12 / nn;
				}
			}
		}
		// ねじれじゃない位置
		return min(
			min( DistancePointSegmentSq( l1p1, l2p1, l2p2 ),
			DistancePointSegmentSq( l1p2, l2p1, l2p2 ) ),
			min(DistancePointSegmentSq( l2p1, l1p1, l1p2 ),
			DistancePointSegmentSq( l2p2, l1p1, l1p2 ) )
			);
	}
Beispiel #6
0
	// 点と線分の距離の平方を返す(カプセル用)
	float	Collision::DistancePointSegmentSq( const Vector3& p1, const Vector3& l1p1, const Vector3& l1p2 )
	{
		Vector3 v1 = p1 - l1p1;
		Vector3 v2 = l1p2 - l1p1;
		float v1v2 = Vector3Dot( v1, v2 );
		if ( v1v2 <= 0.0f ) return v1.LengthSq();
		float v2v2 = v2.LengthSq();
		if ( v2v2 <= v1v2 ) {
			Vector3 v3 = p1 - l1p2;
			return v3.LengthSq();
		}
		return v1.LengthSq() - v1v2 * v1v2 / v2v2;
	}
Beispiel #7
0
	//	動くオブジェクトの反射
	bool	Collision::GetReflect( iexMesh* org, Vector3& pos, Vector3& vec, float rate ) 
	{
		// オブジェクトの逆行列を算出
		org->Update();
		Matrix mat = org->TransMatrix;
		Matrix invMat;	// 逆行列
		D3DXMatrixInverse( &invMat, null, &mat );

		// 逆行列でレイをローカル化
		Vector3 invVec;
		invVec.x = invMat._11 * vec.x + invMat._21 * vec.y + invMat._31 * vec.z;
		invVec.y = invMat._12 * vec.x + invMat._22 * vec.y + invMat._32 * vec.z;
		invVec.z = invMat._13 * vec.x + invMat._23 * vec.y + invMat._33 * vec.z;

		Vector3 invPos;
		invPos.x = invMat._11 * pos.x + invMat._21 * pos.y + invMat._31 * pos.z + invMat._41;
		invPos.y = invMat._12 * pos.x + invMat._22 * pos.y + invMat._32 * pos.z + invMat._42;
		invPos.z = invMat._13 * pos.x + invMat._23 * pos.y + invMat._33 * pos.z + invMat._43;

		Vector3 v = invVec;
		Vector3 p = invPos;
		Vector3 out;
		float d = 100.0f;
		if ( org->RayPick( &out, &p, &v, &d ) >= 0 )
		{
			Vector3 vv = out - p;
			float dd = vv.Length();
			float dm = invVec.Length();
			if ( dd < dm ){
				v.Normalize();		//	法線算出			
				float dot = Vector3Dot( -invVec, v );	// 法線方向に射影
				invVec = v*dot*2.0f - ( -invVec );

				Vector3 p;
				p.x = mat._11 * out.x + mat._21 * out.y + mat._31 * out.z + mat._41;
				p.y = mat._12 * out.x + mat._22 * out.y + mat._32 * out.z + mat._42;
				p.z = mat._13 * out.x + mat._23 * out.y + mat._33 * out.z + mat._43;
				pos = p;

				Vector3 v;
				v.x = mat._11 * invVec.x + mat._21 * invVec.y + mat._31 * invVec.z;
				v.y = mat._12 * invVec.x + mat._22 * invVec.y + mat._32 * invVec.z;
				v.z = mat._13 * invVec.x + mat._23 * invVec.y + mat._33 * invVec.z;
				vec = v*rate;

				return true;
			}
		}
		return false;
	}
Beispiel #8
0
// `計算方向光, 它只跟頂點面向和光源方向有關.`
void CalculateDirectionalLight(Vertex_VCN *pVertices, int num_vertices)
{
	for ( int i=0; i<num_vertices; i++ )
	{
		// `求出轉換後在世界座標系的頂點面向, RotateVector函式只做旋轉, 忽略位移.`
		Vector4 normal = g_world_matrix.RotateVector(pVertices[i].m_Normal);
		// `頂點面向跟光線方向的交角, 決定反射光的強度.`
		Vector4 intensity = Vector3Dot(normal, g_vLightDirection);
		// `把intensity局限在永遠大於0的范圍`
		intensity.Clamp_to_0();
		// `累加上計算出來方向光的強度`
		pVertices[i].m_Color += intensity * g_vLightColor;
		pVertices[i].m_Color.Clamp_to_1();
	}
}
Beispiel #9
0
	//	壁との当たり判定
	bool	Collision::CheckWall( iexMesh* org, const Vector3& pos, Vector3& p_move )
	{
		//org->Update();
		const	float	DIST = 2.0f;	//	壁との距離
		Vector3	p_pos = Vector3(pos.x, pos.y + 1.0f, pos.z);
		Vector3	vec = Vector3(p_move.x, 0.0f, p_move.z);
		vec.Normalize();
		Vector3	takePos;
		float	dist = 100.0f;

		// オブジェクトの逆行列を算出

		if ( org->RayPick( &takePos, &p_pos, &vec, &dist ) != -1 ){
			float	disToWall = Vector3( Vector3( takePos.x, 0.0f, takePos.z ) - Vector3( p_pos.x, 0.0f, p_pos.z ) ).Length();
			if ( disToWall <= DIST )
			{
				//	移動量
				float	move = Vector3( p_move.x, 0.0f, p_move.z ).Length();

				//	プレイヤーからレイの交差点へのベクトル
				Vector3	vPtoWall( takePos - p_pos );
				vPtoWall.y = 0.0f;	vPtoWall.Normalize();
				vec.y = 0.0f;	vec.Normalize();

				//	法線の上方向(?)を求める
				Vector3	vCrossUp;
				Vector3Cross( vCrossUp, vec, vPtoWall );
				vCrossUp.Normalize();

				//	法線の上方向(?)と法線の外積から滑る方向を計算
				Vector3	vCrossSide;
				Vector3Cross( vCrossSide, vCrossUp, vec );
				vCrossSide.Normalize();

				//	法線とプレーヤーからレイの交差点へのベクトルの内積
				float	dotNP = Vector3Dot( vec, vPtoWall );

				//	移動量の調整
				p_move.x = vCrossSide.x * move * ( dotNP + 1.0f );
				p_move.z = vCrossSide.z * move * ( dotNP + 1.0f );

				return	true;
			}
		}

		return	false;
	}
Beispiel #10
0
bool Flyer::Can_do(BasePlayer *player)
{
	if( broken )
		return false;

	// 位置と向き判定
	Vector3 ppos; // playerの位置

	ppos = player->Get_pos();

	Vector3 poster_player( ppos - position ); // ポスターからプレイヤー

	// 距離
	if( poster_player.LengthSq() > DIST * DIST ) return false;

	// 向き
	if( Vector3Dot( player->Get_forward(), poster_player ) >= 0.0f ) return false;

	return true;
}
Beispiel #11
0
void  Deferred::AddPLSdata(const Vector3 pos, const Vector3 color, const float range, const float power)
{
	PLSData data;

	// 今のままだとカリングが意味をなさない
	Matrix mWV = matView;// ビュー行列
						 // 視錐台カリング処理
	Vector3 flont(mWV._13, mWV._23, mWV._33);
	flont.Normalize();
	Vector3 dir = pos - (m_vViewPos - flont * range);			//レンジの値分下げて、カリングを緩める。
	dir.Normalize();
	float dot = Vector3Dot(dir, flont);
	if (dot < 0.2f)
	{
		return;			// 見えていないポイントライトを消去
	}

	// ワールド座標のデータも詰める
	data.wpos = pos;

	// カメラ空間変換
	Matrix mat = matView;
	data.pos.x = pos.x * mat._11 + pos.y * mat._21 + pos.z * mat._31 + mat._41;
	data.pos.y = pos.x * mat._12 + pos.y * mat._22 + pos.z * mat._32 + mat._42;
	data.pos.z = pos.x * mat._13 + pos.y * mat._23 + pos.z * mat._33 + mat._43;

	data.range = range;
	data.color = color;
	data.power = power;


	if ((int)PLSdata.size() >= PLS_MAX)assert(0);

	// 配列に加える
	PLSdata.push_back(data);



}
Beispiel #12
0
float Vector3Length(const float *a)
{
	float lengthSquared = Vector3Dot(a,a);
	float length = sqrt(lengthSquared);
	return length;
}
Beispiel #13
0
LUX_API void lxMatrix44RotateAngle(lxMatrix44PTR mat, lxVector3PTR from, lxVector3PTR to){
  /*
  Vector3 vs;
  Vector3 vt;
  Vector3 v;
  float ca;

  Vector3NormalizedA(from);
  Vector3NormalizedA(to);

  Vector3Cross(vs,from, to);
  // axis multiplied by sin

  Vector3Copy(v,vs);
  Vector3NormalizedA(v);
  // axis of rotation
  ca = Vector3Dot(from, to) ; // cos angle

  Vector3Copy(vt,v);
  Vector3Scale(v,v,(1.0f -ca));

  Matrix44Identity(m);
  mat[0] = vt[0] * v[0] + ca;
  mat[5] = vt[1] * v[1] + ca;
  mat[10] = vt[2] * v[2] + ca;

  vt[0] *= v[1];
  vt[2] *= v[0];
  vt[1] *= v[2];

  mat[1] = vt[0] - vs[2];
  mat[2] = vt[2] + vs[1];
  mat[4] = vt[0] + vs[2];
  mat[6] = vt[1] - vs[0];
  mat[8] = vt[2] - vs[1];
  mat[9] = vt[1] + vs[0];
  */
  // http://lists.apple.com/archives/mac-opengl/2001/Jan/msg00059.html
  // Author: Tomas Moller, 1999
#define M(row,col) mat[row*4+col]

  float v[3];
  float e,h;

  lxVector3Normalized(from);
  lxVector3Normalized(to);

  lxVector3Cross(v,from,to);
  e=lxVector3Dot(from,to);

  if(e>1.0-LUX_FLOAT_EPSILON) // "from" almost or equal to "to"-vector?
  {
    // return identity
    M(0, 0)=1.0; M(0, 1)=0.0; M(0, 2)=0.0;
    M(1, 0)=0.0; M(1, 1)=1.0; M(1, 2)=0.0;
    M(2, 0)=0.0; M(2, 1)=0.0; M(2, 2)=1.0;
  }
  else if(e<-1.0+LUX_FLOAT_EPSILON) // "from" almost or equal to negated "to"?
  {
    float up[3],left[3];
    float fxx,fyy,fzz,fxy,fxz,fyz;
    float uxx,uyy,uzz,uxy,uxz,uyz;
    float lxx,lyy,lzz,lxy,lxz,lyz;
    // left=CROSS(from, (1,0,0))
    left[0]=0.0; left[1]=from[2]; left[2]=-from[1];
    if(lxVector3Dot(left,left)<LUX_FLOAT_EPSILON) // was left=CROSS(from,(1,0,0)) a good choice?
    {
      // here we now that left = CROSS(from, (1,0,0)) will be a good choice
      left[0]=-from[2]; left[1]=0.0; left[2]=from[0];
    }
    // normalize "left"
    lxVector3Normalized(left);
    lxVector3Cross(up,left,from);
    // now we have a coordinate system, i.e., a basis;
    // M=(from, up, left), and we want to rotate to:
    // N=(-from, up, -left). This is done with the mat:
    // N*M^T where M^T is the transpose of M
    fxx=-from[0]*from[0]; fyy=-from[1]*from[1]; fzz=-from[2]*from[2];
    fxy=-from[0]*from[1]; fxz=-from[0]*from[2]; fyz=-from[1]*from[2];

    uxx=up[0]*up[0]; uyy=up[1]*up[1]; uzz=up[2]*up[2];
    uxy=up[0]*up[1]; uxz=up[0]*up[2]; uyz=up[1]*up[2];

    lxx=-left[0]*left[0]; lyy=-left[1]*left[1]; lzz=-left[2]*left[2];
    lxy=-left[0]*left[1]; lxz=-left[0]*left[2]; lyz=-left[1]*left[2];
    // symmetric mat
    M(0, 0)=fxx+uxx+lxx; M(0, 1)=fxy+uxy+lxy; M(0, 2)=fxz+uxz+lxz;
    M(1, 0)=M(0, 1); M(1, 1)=fyy+uyy+lyy; M(1, 2)=fyz+uyz+lyz;
    M(2, 0)=M(0, 2); M(2, 1)=M(1, 2); M(2, 2)=fzz+uzz+lzz;
  }
  else // the most common case, unless "from"="to", or "from"=-"to"
  {
#if 0
    // unoptimized version - a good compiler will optimize this.
    h=(1.0-e)/Vector3Dot(v,v);
    M(0, 0)=e+h*v[0]*v[0]; M(0, 1)=h*v[0]*v[1]-v[2]; M(0,
      2)=h*v[0]*v[2]+v[1];
    M(1, 0)=h*v[0]*v[1]+v[2]; M(1, 1)=e+h*v[1]*v[1]; M(1,
      2)h*v[1]*v[2]-v[0];
    M(2, 0)=h*v[0]*v[2]-v[1]; M(2, 1)=h*v[1]*v[2]+v[0]; M(2,
      2)=e+h*v[2]*v[2];
#else
    // ...otherwise use this hand optimized version (9 mults less)
    float hvx,hvz,hvxy,hvxz,hvyz;
    //h=(1.0-e)/Vector3Dot(v,v);
    h = 1.0f/(1+e);
    hvx=h*v[0];
    hvz=h*v[2];
    hvxy=hvx*v[1];
    hvxz=hvx*v[2];
    hvyz=hvz*v[1];
    M(0, 0)=e+hvx*v[0]; M(0, 1)=hvxy-v[2]; M(0, 2)=hvxz+v[1];
    M(1, 0)=hvxy+v[2]; M(1, 1)=e+h*v[1]*v[1]; M(1, 2)=hvyz-v[0];
    M(2, 0)=hvxz-v[1]; M(2, 1)=hvyz+v[0]; M(2, 2)=e+hvz*v[2];
#endif
  }
#undef M

}
Beispiel #14
0
// 追加した関数
void iexMesh::NearestPoint( NearestPointOut *out, const Vector3 &inPos )
{
	//	情報取得	
	u32 fvf = lpMesh->GetFVF();
	//	頂点サイズ計算
	int vertexSize = D3DXGetFVFVertexSize( fvf ) / sizeof( float );
	//	バッファロック
	float	*pVertices;
	u16		*pIndices;
	u32 numIndices = lpMesh->GetNumFaces();
	lpMesh->LockVertexBuffer( D3DLOCK_READONLY, ( void** ) &pVertices );
	lpMesh->LockIndexBuffer( D3DLOCK_READONLY, ( void** ) &pIndices );

	struct
	{
		Vector3 vertex[3];
		Vector3	normal;
		Vector3 line[3];

		// 頂点情報から残りの情報を計算
		inline void ComputeFromVertex()
		{
			line[1] = vertex[2] - vertex[1];
			line[2] = vertex[3] - vertex[2];
			line[3] = vertex[1] - vertex[3];

			Vector3Cross( normal, line[1], line[2] );
			normal.Normalize();
		}
	}triangle; // 三角ポリゴン

	out->length = FLT_MAX;

	for( u32 j = 0; j < numIndices; j++ )
	{
		//	面頂点取得
		{
			int index = pIndices[j * 3 + 0] * vertexSize;
			triangle.vertex[1].x = pVertices[index];	triangle.vertex[1].y = pVertices[index + 1];	triangle.vertex[1].z = pVertices[index + 2];

			index = pIndices[j * 3 + 1] * vertexSize;
			triangle.vertex[2].x = pVertices[index];	triangle.vertex[2].y = pVertices[index + 1];	triangle.vertex[2].z = pVertices[index + 2];

			index = pIndices[j * 3 + 2] * vertexSize;
			triangle.vertex[3].x = pVertices[index];	triangle.vertex[3].y = pVertices[index + 1];	triangle.vertex[3].z = pVertices[index + 2];
		}

		// 法線と辺計算
		triangle.ComputeFromVertex();

		// 法線方向に距離計算
		FLOAT lengthNormal( 0 );
		lengthNormal = Vector3Dot( ( inPos - triangle.vertex[1] ), triangle.normal );

		// ポリゴンが裏向き
		if( lengthNormal <= 0 )
			continue;

		// 遠い
		if( lengthNormal > out->length )
			continue;

		Vector3 nearestPos( 0, 0, 0 );
		// とりあえず無限平面上で
		nearestPos = inPos - ( triangle.normal * lengthNormal );

		Vector3 decisionVector( 0, 0, 0 );
		// 内点判定
		for( unsigned int i = 0; i < 3; i++ )
		{
			Vector3Cross( decisionVector, ( triangle.vertex[i] - nearestPos ), triangle.line[i] );
			// 外にあった場合
			if( Vector3Dot( decisionVector, triangle.normal ) < 0 )
			{
				// nearestPosを辺上の最接近点へ移動
				float t = triangle.line[i].LengthSq();
				if( t != 0 ) // 辺上へ
					t = Vector3Dot( ( nearestPos - triangle.vertex[i] ), triangle.line[i] ) / t;
				// 頂点へ
				if( t < 0 ) t = 0;
				else if( t > 1 )t = 1;
				// 移動
				nearestPos = triangle.vertex[i] + triangle.line[i] * t;
			}
		}

		// 距離判定
		float length = ( nearestPos - inPos ).Length();
		if( length > out->length )
			continue;


		out->length = length;
		out->Normal = triangle.normal;
		out->Pos = nearestPos;
	}

	//	バッファアンロック
	lpMesh->UnlockVertexBuffer();
	lpMesh->UnlockIndexBuffer();
}
Beispiel #15
0
//------------------------------------------------------
//		上下最適化
//------------------------------------------------------
int	iexMesh::RayPickUD( Vector3* out, Vector3* pos, Vector3* vec, float *Dist )
{
	float	t, neart;
	float	vy;
	int		ret = -1;

	int		VertexSize;

	Vector3	p = *pos;
	vy = vec->y;

	neart = *Dist;

	//	情報取得	
	int fvf = lpMesh->GetFVF();
	//	頂点サイズ計算
	VertexSize = D3DXGetFVFVertexSize(fvf) / sizeof(float);

	//	バッファロック
	float	*pVertices;
	u16		*pIndices;
	int NumIndices = lpMesh->GetNumFaces();
	lpMesh->LockVertexBuffer( D3DLOCK_READONLY , (void**)&pVertices );
	lpMesh->LockIndexBuffer( D3DLOCK_READONLY , (void**)&pIndices );

	Vector	l1, l2, l3;
	Vector	p1, p2, p3;
	Vector v[3];
	Vector n;

	for( int j=0 ; j<NumIndices ; j++ )
	{
		//	面頂点取得
		int a = pIndices[j*3+0] * VertexSize;
		int b = pIndices[j*3+1] * VertexSize;
		int c = pIndices[j*3+2] * VertexSize;

		v[0].x = pVertices[a];	v[1].x = pVertices[b];	v[2].x = pVertices[c];
		if( v[0].x > p.x && v[1].x > p.x && v[2].x > p.x ) continue;

		v[0].z = pVertices[a+2];	v[1].z = pVertices[b+2];	v[2].z = pVertices[c+2];
		if( v[0].z > p.z && v[1].z > p.z && v[2].z > p.z ) continue;

		v[0].y = pVertices[a+1];	v[1].y = pVertices[b+1];	v[2].y = pVertices[c+1];

		//	内点判定(全外積がマイナス)		
		l1.x = v[1].x - v[0].x;
		l1.z = v[1].z - v[0].z;
		p1.x = v[0].x - p.x;
		p1.z = v[0].z - p.z;
		if( (p1.x*l1.z - p1.z*l1.x)*vy < 0 ) continue;

		l2.x = v[2].x - v[1].x;
		l2.z = v[2].z - v[1].z;
		p2.x = v[1].x - p.x;
		p2.z = v[1].z - p.z;
		if( (p2.x*l2.z - p2.z*l2.x)*vy < 0 ) continue;

		l3.x = v[0].x - v[2].x;
		l3.z = v[0].z - v[2].z;
		p3.x = v[2].x - p.x;
		p3.z = v[2].z - p.z;
		if( (p3.x*l3.z - p3.z*l3.x)*vy < 0 ) continue;

		//	外積による法線算出		
		l1.y = v[1].y - v[0].y;
		l2.y = v[2].y - v[1].y;
		Vector3Cross( n, l1, l2 );
		//	表裏判定
		if( vy*n.y >= 0 ) continue;

		//	交点算出
		p1.y = v[0].y - p.y;
		t = Vector3Dot( n, p1 ) / (n.y*vy);
		if( t < .0f || t > neart ) continue;

		*vec = n;
		ret = j;
		neart = t;
	}
	lpMesh->UnlockVertexBuffer();
	lpMesh->UnlockIndexBuffer();

	out->y = neart*vy + p.y;
	out->x = pos->x;
	out->z = pos->z;
	*Dist = neart;

	return	ret;
}
Beispiel #16
0
//**************************************************************************************************
//
//		レイピック
//
//**************************************************************************************************
//------------------------------------------------------
//		レイピック
//------------------------------------------------------
int	iexMesh::RayPick( Vector3* out, Vector3* pos, Vector3* vec, float *Dist )
{
	int		ret = -1;

	if( vec->x == .0f && vec->z == .0f ) return RayPickUD( out, pos, vec, Dist );

	Vector3 p = *pos;
	Vector3 vv = *vec;

	float neart = *Dist;
	float dist = *Dist;
	dist = dist*dist;
	*out = p;
	//	情報取得	
	u32 fvf = lpMesh->GetFVF();
	//	頂点サイズ計算
	int VertexSize = D3DXGetFVFVertexSize(fvf) / sizeof(float);

	//	バッファロック
	float	*pVertices;
	u16		*pIndices;
	u32 NumIndices = lpMesh->GetNumFaces();
	lpMesh->LockVertexBuffer( D3DLOCK_READONLY, (void**)&pVertices );
	lpMesh->LockIndexBuffer( D3DLOCK_READONLY, (void**)&pIndices );

	Vector3 v1, v2, v3;
	Vector3	n;
	Vector3	l1, l2, l3;
	Vector3	temp;
	Vector3	cp;

	Vector3 p1, p2, p3;

	for( u32 j=0 ; j<NumIndices ; j++ )
	{
		//	面頂点取得
		int a = pIndices[j*3+0] * VertexSize;
		v1.x = pVertices[a];	v1.y = pVertices[a+1];	v1.z = pVertices[a+2];

		int b = pIndices[j*3+1] * VertexSize;
		v2.x = pVertices[b];	v2.y = pVertices[b+1];	v2.z = pVertices[b+2];

		int c = pIndices[j*3+2] * VertexSize;
		v3.x = pVertices[c];	v3.y = pVertices[c+1];	v3.z = pVertices[c+2];
		
		//	距離判定
		//Vector3	ss = (v1 + v2 + v3) / 3.0f - p;
		//if( ss.LengthSq() > dist ) continue;
		l1.x = v2.x - v1.x;
		l1.y = v2.y - v1.y;
		l1.z = v2.z - v1.z;
		l2.x = v3.x - v2.x;
		l2.y = v3.y - v2.y;
		l2.z = v3.z - v2.z;
		
		//	外積による法線算出		
		Vector3Cross( n, l1, l2 );
		//	内積の結果がプラスならば裏向き
		float dot = Vector3Dot( vv, n );
		if( dot >= 0 ) continue;
		//	交点算出
		p1.x = v1.x - p.x;
		p1.y = v1.y - p.y;
		p1.z = v1.z - p.z;
		float t = Vector3Dot( n, p1 ) / dot;
		if( t < .0f || t > neart ) continue;

		cp.x = vv.x*t + p.x;
		cp.y = vv.y*t + p.y;
		cp.z = vv.z*t + p.z;
		//	内点判定
		p1.x = v1.x - cp.x;
		p1.y = v1.y - cp.y;
		p1.z = v1.z - cp.z;
		
		Vector3Cross( temp, p1, l1 );
		if( Vector3Dot(temp, n) < .0f ) continue;

		p2.x = v2.x - cp.x;
		p2.y = v2.y - cp.y;
		p2.z = v2.z - cp.z;
		Vector3Cross( temp, p2, l2 );
		if( Vector3Dot(temp, n) < .0f ) continue;

		l3.x = v1.x - v3.x;
		l3.y = v1.y - v3.y;
		l3.z = v1.z - v3.z;
		p3.x = v3.x - cp.x;
		p3.y = v3.y - cp.y;
		p3.z = v3.z - cp.z;
		Vector3Cross( temp, p3, l3 );
		if( Vector3Dot(temp, n) < .0f ) continue;

		*out = cp;
		*vec = n;
		ret = j;
		neart = t;
	}
	lpMesh->UnlockVertexBuffer();
	lpMesh->UnlockIndexBuffer();
	*Dist = neart;

	return	ret;
}
Beispiel #17
0
float Vector3LengthSq(const LPVECTOR3 pVec) {
	return Vector3Dot(pVec, pVec);
}