bool CollisionTester::RayTriangleTest( const Ray3& ray, const CVector3& A, const CVector3& B, const CVector3& C, CVector3& isect, float& s, float& t ) { const CVector3& O = ray.mOrigin; const CVector3& D = ray.mDirection; /////////////////////////////////////////////////// // first calc intersection to plane CVector3 vab = (B-A); CVector3 vac = (C-A); CVector3 Nabc = vab.Cross(vac); float dist_O_to_P = -(O-A).Dot(Nabc)/(D.Dot(Nabc)); isect = O+(D*dist_O_to_P); // plane_isect if( dist_O_to_P<0.0f ) return false; /////////////////////////////////////////////////// // calc s and t (pseudo-barycentric method) //CVector3 vop = (isect-O); // debugging? CVector3 voa = (A-O); CVector3 vob = (B-O); CVector3 voc = (C-O); CPlane PlaneOCA( voc.Cross(voa).Normal(), O ); CPlane PlaneOBA( voa.Cross(vob).Normal(), O ); t = PlaneOCA.GetPointDistance( isect )/PlaneOCA.GetPointDistance(B); s = PlaneOBA.GetPointDistance( isect )/PlaneOBA.GetPointDistance(C); return ((t>=0.0f)&&(t<=1.0f)&&(s>=0.0f)&&(s<=1.0f)); }
CVector3 cRenderWorker::NormalMapShader(const sShaderInputData &input) { cObjectData objectData = data->objectData[input.objectId]; CVector3 texX, texY; double texturePixelSize = 1.0; CVector2<double> texPoint = TextureMapping(input.point, input.normal, objectData, input.material, &texX, &texY) + CVector2<double>(0.5, 0.5); // mipmapping - calculation of texture pixel size double delta = CalcDelta(input.point); double deltaTexX = ((TextureMapping(input.point + texX * delta, input.normal, objectData, input.material) + CVector2<double>(0.5, 0.5)) - texPoint) .Length(); double deltaTexY = ((TextureMapping(input.point + texY * delta, input.normal, objectData, input.material) + CVector2<double>(0.5, 0.5)) - texPoint) .Length(); deltaTexX = deltaTexX / fabs(input.viewVector.Dot(input.normal)); deltaTexY = deltaTexY / fabs(input.viewVector.Dot(input.normal)); texturePixelSize = 1.0 / max(deltaTexX, deltaTexY); CVector3 n = input.normal; // tangent vectors: CVector3 t = n.Cross(texX); t.Normalize(); CVector3 b = n.Cross(texY); b.Normalize(); CMatrix33 tbn(b, t, n); CVector3 tex; if (input.material->normalMapTextureFromBumpmap) { tex = input.material->normalMapTexture.NormalMapFromBumpMap( texPoint, input.material->normalMapTextureHeight, texturePixelSize); } else { tex = input.material->normalMapTexture.NormalMap( texPoint, input.material->normalMapTextureHeight, texturePixelSize); } CVector3 result = tbn * tex; result.Normalize(); return result; }
CVector3 CVector3::RotateAroundVectorByAngle(CVector3 axis, double angle) { CVector3 vector = *this * cos(angle); vector += (axis.Cross(*this)) * sin(angle); vector += axis * axis.Dot(*this) * (1 - cos(angle)); return vector; }
CVector3 InterpolateVector(CVector3 vA, CVector3 vB, double blend) { if (blend == 0) return vA; else if (blend == 1) return vB; CVector3 cross; cross.Cross(vA, vB); cross.NormalizeInPlace(); double lengthA = vA.GetLength(); double lengthB = vB.GetLength(); double length = lengthB * blend + lengthA * (1 - blend); double a = vA.GetAngle(vB); CVector3 v = rotateVectorAlongAxis(vA, cross, a * blend); v.NormalizeInPlace(); v.ScaleInPlace(length); return v; }
/*! * @brief 衝突検出と解決。 *@param[in] nextPosition 次の座標。 */ void EnemyTest::CollisionDetectAndResolve(CVector3 nextPosition) { //XZ平面を調べる。 { int loopCount = 0; while (true) { CVector3 addPos; addPos.Subtract(nextPosition, position); CVector3 posTmp = position; posTmp.y += radius + 0.2f; btTransform start, end; start.setIdentity(); end.setIdentity(); start.setOrigin(*(btVector3*)(&posTmp)); CVector3 newPos; SweepResultWall callback; callback.startPos = position; CVector3 addPosXZ = addPos; addPosXZ.y = 0.0f; if (addPosXZ.Length() > 0.0001f) { newPos.Add(posTmp, addPosXZ); end.setOrigin(btVector3(newPos.x, newPos.y, newPos.z)); PhysicsWorld().ConvexSweepTest((const btConvexShape*)collider.GetBody(), start, end, callback); } if (callback.isHit) { //当たった。 float t = fabsf(acosf(callback.hitNormal.Dot(CVector3::Up))); if (t >= CMath::PI * 0.3f) { //壁。 nextPosition.x = callback.hitPos.x; nextPosition.z = callback.hitPos.z; //半径分押し戻す。 CVector3 hitNormalXZ = callback.hitNormal; hitNormalXZ.y = 0.0f; hitNormalXZ.Normalize(); CVector3 t = hitNormalXZ; t.Scale(radius); nextPosition.Add(t); //続いて壁に沿って滑らせる。 t.Cross(hitNormalXZ, CVector3::Up); t.Normalize(); //押し戻しで動いた分は減算する。 CVector3 t2; t2.Subtract(nextPosition, position); t2.y = 0.0f; addPosXZ.Subtract(t2); t.Scale(t.Dot(addPosXZ)); nextPosition.Add(t); } } else { //どことも当たらないので終わり。 break; } loopCount++; if (loopCount == 5) { break; } } } //下方向を調べる。 { CVector3 addPos; addPos.Subtract(nextPosition, position); btTransform start, end; start.setIdentity(); end.setIdentity(); start.setOrigin(btVector3(position.x, position.y + radius, position.z)); CVector3 newPos; SweepResultGround callback; callback.startPos = position; if (addPos.y < 0.0f) { newPos = (*(CVector3*)&start.getOrigin()); newPos.y += addPos.y; end.setOrigin(btVector3(newPos.x, newPos.y, newPos.z)); PhysicsWorld().ConvexSweepTest((const btConvexShape*)collider.GetBody(), start, end, callback); } if (callback.isHit) { //当たった。 float t = fabsf(acosf(callback.hitNormal.Dot(CVector3::Up))); if (t < CMath::PI * 0.3f) { //地面。 CVector3 Circle; float x = 0.0f; float offset = 0.0f; //押し戻す量。 Circle = CVector3::Zero; Circle = position; Circle.y = callback.hitPos.y;//円の中心 CVector3 v; v.Subtract(Circle, callback.hitPos); x = v.Length();//物体の角とプレイヤーの間の横幅の距離が求まる。 offset = sqrt(max(0.0f, radius*radius - x*x));//yの平方根を求める。 moveSpeed.y = 0.0f; isJump = false; nextPosition.y = callback.hitPos.y + offset - radius; } } } position = nextPosition; }
void CSoundManager::FillCurrentBuffer( Float* a_CurrentBuffer, const Uint a_SoundChannels, const Uint a_SampleRate, const Uint a_SamplesInBuffer ) { m_SoundsCriticalSection.Enter(); m_SampleRate = a_SampleRate; //If this is the first time we enter create and memset the echo buffer if ( m_EchoBuffer == NULL ) { m_EchoBuffer = new Float[a_SamplesInBuffer * m_EchoCount ]; memset( m_EchoBuffer, 0, sizeof(Float) * a_SamplesInBuffer * m_EchoCount ); m_ReadPositionInEchoBuffer = m_SampleRate * ( ( m_EchoDelayMS / 1000.0f ) / 1.0f ); } //Calculate listener data m_ListenersCritcalSection.Enter(); CVector3 up = m_ActiveListener->GetUp(); CVector3 lookAtCrossUp = m_ActiveListener->GetDirection(); lookAtCrossUp = lookAtCrossUp.Cross( up ); lookAtCrossUp.Normalize(); CVector3 listenerPosition = m_ActiveListener->GetWorldPosition(); m_ListenersCritcalSection.Leave(); //Loop through sound to let them fill the buffer m_SoundIt = m_SoundsMap.begin(); while( m_SoundIt != m_SoundsMap.end() ) { if ( m_SoundIt->second->IsPlaying() == true ) { m_SoundIt->second->FillCurrentBuffer( a_SoundChannels, a_SampleRate, a_SamplesInBuffer, lookAtCrossUp, listenerPosition, m_GlobalAttenuation ); } m_SoundIt++; } Float* targetPointer = a_CurrentBuffer; Float* sourcePointer; //Brickwall max Float max = 0.0f; //Loop again now collecting the buffers and adding them into a final buffer m_SoundIt = m_SoundsMap.begin(); Float oneOverSize = 1.0f / m_SoundsMap.size(); Float value; while( m_SoundIt != m_SoundsMap.end() ) { targetPointer = a_CurrentBuffer; if ( m_SoundIt->second->IsPlaying() == true ) { sourcePointer = m_SoundIt->second->GetCurrentBuffer(); for ( Uint i = 0; i < a_SamplesInBuffer; ++i ) { //Multiply with globalvolume and the one-over ( kind of ugly to prevent clipping ) value = ( *sourcePointer ) * m_GlobalVolume; //Anti distortion if ( m_DistortFunction == AntiDistortNumChannels ) { value *= oneOverSize; } else if ( m_DistortFunction == AntiDistortMagicValue ) { value *= m_MagicValue; } *targetPointer += value; Float abs = fabs( *targetPointer ); if ( abs > max ) { max = abs; } sourcePointer++; targetPointer++; } } m_SoundIt++; } //Apply echo if ( m_EchoActive == true ) { targetPointer = a_CurrentBuffer; for ( Uint i = 0; i < a_SamplesInBuffer; ++i ) { //Write to the current buffer *targetPointer += ( m_EchoBuffer[m_ReadPositionInEchoBuffer++] ); //If we reach the end of buffer wrap around if ( m_ReadPositionInEchoBuffer >= ( a_SamplesInBuffer * m_EchoCount ) ) { m_ReadPositionInEchoBuffer = 0; } //Abs for echo Float abs = fabs( *targetPointer ); if ( abs > max ) { max = abs; } //Increment target point targetPointer++; //Write current buffer into echo buffer m_EchoBuffer[m_PositionInEchoBuffer++] = a_CurrentBuffer[i] * m_EchoDecay; if ( m_PositionInEchoBuffer >= ( a_SamplesInBuffer * m_EchoCount ) ) m_PositionInEchoBuffer = 0; } } //Brickwall Float oneOverMax = 1.0f / max; if ( m_DistortFunction == AntiDistortBrickWall ) for ( Uint i = 0; i < a_SamplesInBuffer; ++i ) { a_CurrentBuffer[i] *= oneOverMax; } m_SoundsCriticalSection.Leave(); }
CVector2<double> TextureMapping(CVector3 inPoint, CVector3 normalVector, const cObjectData &objectData, const cMaterial *material, CVector3 *textureVectorX, CVector3 *textureVectorY) { CVector2<double> textureCoordinates; CVector3 point = inPoint - objectData.position; point = objectData.rotationMatrix.RotateVector(point); point /= objectData.size; point = material->rotMatrix.RotateVector(point); switch (material->textureMappingType) { case cMaterial::mappingPlanar: { textureCoordinates = CVector2<double>(point.x, point.y); textureCoordinates.x /= -material->textureScale.x; textureCoordinates.y /= material->textureScale.y; textureCoordinates.x -= material->textureCenter.x; textureCoordinates.y -= material->textureCenter.y; if (textureVectorX && textureVectorY) { CVector3 texX(1.0, 0.0, 0.0); texX = objectData.rotationMatrix.Transpose().RotateVector(texX); texX = material->rotMatrix.Transpose().RotateVector(texX); *textureVectorX = texX; CVector3 texY(0.0, -1.0, 0.0); texY = objectData.rotationMatrix.Transpose().RotateVector(texY); texY = material->rotMatrix.Transpose().RotateVector(texY); *textureVectorY = texY; } break; } case cMaterial::mappingCylindrical: { double alphaTexture = fmod(point.GetAlpha() + 2.0 * M_PI, 2.0 * M_PI); textureCoordinates.x = alphaTexture / (2.0 * M_PI); textureCoordinates.y = -point.z; textureCoordinates.x /= material->textureScale.x; textureCoordinates.y /= material->textureScale.y; textureCoordinates.x -= material->textureCenter.x; textureCoordinates.y -= material->textureCenter.y; if (textureVectorX && textureVectorY) { CVector3 texY(0.0, 0.0, 1.0); CVector3 texX = point.Cross(texY); texX = objectData.rotationMatrix.Transpose().RotateVector(texX); texX = material->rotMatrix.Transpose().RotateVector(texX); *textureVectorX = texX; texY = objectData.rotationMatrix.Transpose().RotateVector(texY); texY = material->rotMatrix.Transpose().RotateVector(texY); *textureVectorY = texY; } break; } case cMaterial::mappingSpherical: { double alphaTexture = fmod(point.GetAlpha() + 2.0 * M_PI, 2.0 * M_PI); double betaTexture = -point.GetBeta(); textureCoordinates.x = alphaTexture / (2.0 * M_PI); textureCoordinates.y = (betaTexture / M_PI); textureCoordinates.x /= material->textureScale.x; textureCoordinates.y /= material->textureScale.y; textureCoordinates.x -= material->textureCenter.x; textureCoordinates.y -= material->textureCenter.y; CVector3 texY(0.0, 0.0, -1.0); CVector3 texX = texY.Cross(point); texX.Normalize(); texY = texX.Cross(point); if (textureVectorX && textureVectorY) { texX = objectData.rotationMatrix.Transpose().RotateVector(texX); texX = material->rotMatrix.Transpose().RotateVector(texX); *textureVectorX = texX; texY = objectData.rotationMatrix.Transpose().RotateVector(texY); texY = material->rotMatrix.Transpose().RotateVector(texY); *textureVectorY = texY; } break; } case cMaterial::mappingCubic: { point /= material->textureScale; point -= material->textureCenter; CVector3 texX, texY; if (fabs(normalVector.x) > fabs(normalVector.y)) { if (fabs(normalVector.x) > fabs(normalVector.z)) { // x if (normalVector.x > 0) textureCoordinates = CVector2<double>(point.y, -point.z); else textureCoordinates = CVector2<double>(-point.y, -point.z); if (textureVectorX && textureVectorY) { if (normalVector.x > 0) { texX = CVector3(0.0, -1.0, 0.0); texY = CVector3(0.0, 0.0, 1.0); } else { texX = CVector3(0.0, 1.0, 0.0); texY = CVector3(0.0, 0.0, 1.0); } } } else { // z if (normalVector.z > 0) textureCoordinates = CVector2<double>(-point.x, point.y); else textureCoordinates = CVector2<double>(point.x, point.y); if (textureVectorX && textureVectorY) { if (normalVector.z > 0) { texX = CVector3(1.0, 0.0, 0.0); texY = CVector3(0.0, -1.0, 0.0); } else { texX = CVector3(-1.0, 0.0, 0.0); texY = CVector3(0.0, -1.0, 0.0); } } } } else { if (fabs(normalVector.y) > fabs(normalVector.z)) { // y if (normalVector.y > 0) textureCoordinates = CVector2<double>(-point.x, -point.z); else textureCoordinates = CVector2<double>(point.x, -point.z); if (textureVectorX && textureVectorY) { if (normalVector.y > 0) { texX = CVector3(1.0, 0.0, 0.0); texY = CVector3(0.0, 0.0, 1.0); } else { texX = CVector3(-1.0, 0.0, 0.0); texY = CVector3(0.0, 0.0, 1.0); } } } else { // z if (normalVector.z > 0) textureCoordinates = CVector2<double>(-point.x, point.y); else textureCoordinates = CVector2<double>(point.x, point.y); if (textureVectorX && textureVectorY) { if (normalVector.z > 0) { texX = CVector3(1.0, 0.0, 0.0); texY = CVector3(0.0, -1.0, 0.0); } else { texX = CVector3(-1.0, 0.0, 0.0); texY = CVector3(0.0, -1.0, 0.0); } } } } if (textureVectorX && textureVectorY) { texX = objectData.rotationMatrix.Transpose().RotateVector(texX); texX = material->rotMatrix.Transpose().RotateVector(texX); *textureVectorX = texX; texY = objectData.rotationMatrix.Transpose().RotateVector(texY); texY = material->rotMatrix.Transpose().RotateVector(texY); *textureVectorY = texY; } break; } } return textureCoordinates; }
void CCamera::LookAt(const CVector3& eye, const CVector3& target, const CVector3& up, HANDEDNESS handedness) { CMatrix4 view; view.Clear(); if(handedness == HANDEDNESS_LEFTHANDED) { //zaxis = normal(At - Eye) //xaxis = normal(cross(Up, zaxis)) //yaxis = cross(zaxis, xaxis) CVector3 axisZ = (target - eye).Normalize(); CVector3 axisX = (up.Cross(axisZ)).Normalize(); CVector3 axisY = axisZ.Cross(axisX); view(0, 0) = axisX.x; view(1, 0) = axisX.y; view(2, 0) = axisX.z; view(3, 0) = -axisX.Dot(eye); view(0, 1) = axisY.x; view(1, 1) = axisY.y; view(2, 1) = axisY.z; view(3, 1) = -axisY.Dot(eye); view(0, 2) = axisZ.x; view(1, 2) = axisZ.y; view(2, 2) = axisZ.z; view(3, 2) = -axisZ.Dot(eye); view(3, 3) = 1; } else { //zaxis = normal(Eye - At) //xaxis = normal(cross(Up, zaxis)) //yaxis = cross(zaxis, xaxis) CVector3 axisZ = (eye - target).Normalize(); CVector3 axisX = (up.Cross(axisZ)).Normalize(); CVector3 axisY = axisZ.Cross(axisX); view(0, 0) = axisX.x; view(1, 0) = axisX.y; view(2, 0) = axisX.z; view(3, 0) = -axisX.Dot(eye); view(0, 1) = axisY.x; view(1, 1) = axisY.y; view(2, 1) = axisY.z; view(3, 1) = -axisY.Dot(eye); view(0, 2) = axisZ.x; view(1, 2) = axisZ.y; view(2, 2) = axisZ.z; view(3, 2) = -axisZ.Dot(eye); view(3, 3) = 1; } m_viewMatrix = view; }