TriangleMesh* DebugGeometryBuilder::createBoxHeadedArrow( float size, const Vector& start, const Vector& end ) { FastFloat simdSize; simdSize.setFromFloat( size ); Vector dir; dir.setSub( end, start ); dir.normalize(); Vector perpVec1, perpVec2; VectorUtil::calculatePerpendicularVector( dir, perpVec1 ); perpVec1.normalize(); perpVec2.setCross( dir, perpVec1 ); perpVec1.mul( simdSize ); perpVec2.mul( simdSize ); // the line std::vector<LitVertex> vertices; std::vector<Face> faces; addCuboid( simdSize, start, end, vertices, faces ); // and the box-shaped tip FastFloat tipSize; tipSize.setFromFloat( 6 * size ); Vector tipEnd; tipEnd.setMulAdd( dir, tipSize, end ); addCuboid( tipSize, end, tipEnd, vertices, faces ); TriangleMesh* mesh = new TriangleMesh( FilePath(), vertices, faces ); return mesh; }
bool Vector::isNormalized() const { FastFloat v; v.setSub( lengthSq(), Float_1 ); v.abs(); return v < Float_1e_4; }
void DebugGeometryBuilder::addCone( const FastFloat& baseSize, const Vector& start, const Vector& end, std::vector< LitVertex >& outVertices, std::vector< Face >& outFaces ) { // calculate additional vectors needed for cuboid construction Vector dir; dir.setSub( end, start ); dir.normalize(); Vector perpVec1, perpVec2; VectorUtil::calculatePerpendicularVector( dir, perpVec1 ); perpVec1.normalize(); perpVec2.setCross( dir, perpVec1 ); perpVec1.mul( baseSize ); perpVec2.mul( baseSize ); // calculate the vertices and outFaces uint firstVtxIdx = outVertices.size(); uint firstFaceIdx = outFaces.size(); for( uint i = 0; i < 5; ++i ) { outVertices.push_back( LitVertex() ); } for( uint i = 0; i < 6; ++i ) { outFaces.push_back( Face() ); } Vector tmpVec; { perpVec1.mul( Float_6 ); perpVec2.mul( Float_6 ); tmpVec.setAdd( start, perpVec1 ); tmpVec.sub( perpVec2 ); tmpVec.store( outVertices[firstVtxIdx + 0].m_coords ); tmpVec.setSub( start, perpVec1 ); tmpVec.sub( perpVec2 ); tmpVec.store( outVertices[firstVtxIdx + 1].m_coords ); tmpVec.setAdd( start, perpVec1 ); tmpVec.add( perpVec2 ); tmpVec.store( outVertices[firstVtxIdx + 2].m_coords ); tmpVec.setSub( start, perpVec1 ); tmpVec.add( perpVec2 ); tmpVec.store( outVertices[firstVtxIdx + 3].m_coords ); FastFloat tipSizeMultiplier; tipSizeMultiplier.setFromFloat( 12 ); tipSizeMultiplier.mul( baseSize ); tmpVec.setMulAdd( dir, tipSizeMultiplier, end ); tmpVec.store( outVertices[firstVtxIdx + 4].m_coords ); // cone bottom outFaces[firstFaceIdx + 0].idx[0] = firstVtxIdx + 0; outFaces[firstFaceIdx + 0].idx[1] = firstVtxIdx + 1; outFaces[firstFaceIdx + 0].idx[2] = firstVtxIdx + 2; outFaces[firstFaceIdx + 1].idx[0] = firstVtxIdx + 1; outFaces[firstFaceIdx + 1].idx[1] = firstVtxIdx + 3; outFaces[firstFaceIdx + 1].idx[2] = firstVtxIdx + 2; // cone top outFaces[firstFaceIdx + 2].idx[0] = firstVtxIdx + 0; outFaces[firstFaceIdx + 2].idx[1] = firstVtxIdx + 4; outFaces[firstFaceIdx + 2].idx[2] = firstVtxIdx + 1; outFaces[firstFaceIdx + 3].idx[0] = firstVtxIdx + 1; outFaces[firstFaceIdx + 3].idx[1] = firstVtxIdx + 4; outFaces[firstFaceIdx + 3].idx[2] = firstVtxIdx + 3; outFaces[firstFaceIdx + 4].idx[0] = firstVtxIdx + 3; outFaces[firstFaceIdx + 4].idx[1] = firstVtxIdx + 4; outFaces[firstFaceIdx + 4].idx[2] = firstVtxIdx + 2; outFaces[firstFaceIdx + 5].idx[0] = firstVtxIdx + 2; outFaces[firstFaceIdx + 5].idx[1] = firstVtxIdx + 4; outFaces[firstFaceIdx + 5].idx[2] = firstVtxIdx + 0; } }
void CameraMovementController::update( float timeElapsed ) { float speedMul =m_uic->isKeyPressed( VK_SHIFT ) ? 4.0f : 1.0f; FastFloat movementSpeed; movementSpeed.setFromFloat( 10.0f * speedMul * timeElapsed ); FastFloat negMovementSpeed; negMovementSpeed.setNeg( movementSpeed ); float rotationSpeed = 0.1f * timeElapsed; // check which keys are pressed m_movementDir[MD_FRONT] = m_uic->isKeyPressed( 'W' ); m_movementDir[MD_BACK] = m_uic->isKeyPressed( 'S' ); m_movementDir[MD_LEFT] = m_uic->isKeyPressed( 'A' ); m_movementDir[MD_RIGHT] = m_uic->isKeyPressed( 'D' ); m_rotating = m_uic->isKeyPressed( VK_RBUTTON ); m_uic->setRelativeMouseMovement( m_rotating ); // process the keys Vector moveVec; if ( m_movementDir[MD_FRONT] ) { moveVec.setMul( m_cameraController->getLookVec(), movementSpeed ); m_cameraController->move( moveVec ); } if ( m_movementDir[MD_BACK] ) { moveVec.setMul( m_cameraController->getLookVec(), negMovementSpeed ); m_cameraController->move( moveVec ); } if ( m_movementDir[MD_LEFT] ) { moveVec.setMul( m_cameraController->getRightVec(), negMovementSpeed ); m_cameraController->move( moveVec ); } if ( m_movementDir[MD_RIGHT] ) { moveVec.setMul( m_cameraController->getRightVec(), movementSpeed ); m_cameraController->move( moveVec ); } if ( m_rotating ) { float mouseSpeedX = m_uic->getMouseSpeed().v[0] * rotationSpeed; float mouseSpeedY = m_uic->getMouseSpeed().v[1] * rotationSpeed; m_cameraController->rotate( mouseSpeedY, mouseSpeedX ); } }
bool Frustum::isInside( const Sphere& sphere ) const { FastFloat negSphereRad; negSphereRad.setNeg( sphere.radius ); for ( int i = 0; i < 6; ++i ) { const FastFloat n = planes[i].dotCoord( sphere.origin ); if ( n < negSphereRad ) { return false; } } return true; }
BehTreeNode::Result BTAMoveWithVelocity::execute( BehaviorTreeRunner& runner ) const { RuntimeDataBuffer& data = runner.data( ); PhysicsCharacterController* characterController = data[m_characterController]; if ( !m_velocity ) { LOG( "BTAMoveWithVelocity: Assign a velocity variable" ); return FAILED; } if ( !m_characterRotation ) { LOG( "BTAMoveWithVelocity: Assign a character rotation variable" ); return FAILED; } if ( !characterController ) { LOG( "BTAMoveWithVelocity: The character doesn't have a PhysicsCharacterController component" ); return FAILED; } StoryBehTreeContext* context = (StoryBehTreeContext*)runner.getContext(); StoryNodeInstance* controlledNodeInstance = context->m_ownerInstance; // calculate displacement TimeController& timeController = TSingleton< TimeController >::getInstance(); Vector movementVelocity = m_velocity->getRuntime( &runner ); characterController->setLinearVelocity( movementVelocity ); // calculate new facing direction and a corresponding orientation { Matrix nodeTransform = controlledNodeInstance->getLocalMtx( ); FastFloat dYaw; dYaw.setFromFloat( m_characterRotation->getRuntime( &runner ) ); Vector angularVelocity; angularVelocity.set( Float_0, Float_0, dYaw ); characterController->setAngularVelocity( angularVelocity ); } return FINISHED; }
void Camera::lookAt( Entity& node, const FastFloat& distance, const Vector& upVec ) { const Matrix& targetNodeMtx = node.getGlobalMtx(); const Vector& targetNodePos = targetNodeMtx.position(); const Vector& targetNodeLookVec = targetNodeMtx.forwardVec(); // I used to normalize the look vector here, but is there a need to do it really? we assume // it's always normalized ASSERT_MSG( targetNodeLookVec.isNormalized(), "Look vector not normalized" ); FastFloat negDist; negDist.setNeg( distance ); Vector newPosition; newPosition.setMul( targetNodeLookVec, negDist ); newPosition.add( targetNodePos ); Matrix lookAtMtx; MatrixUtils::generateLookAtLH( newPosition, targetNodePos, upVec, lookAtMtx ); setLocalMtx( lookAtMtx ); }
void DeferredPointLightRenderer::render( Renderer& renderer, const PointLight* light, const DeferredLightingRenderData& data ) { if ( !m_pixelShader || !m_vertexShader || !m_pointLightMesh ) { return; } Camera& activeCamera = renderer.getActiveCamera(); Matrix globalMtx = light->getGlobalMtx(); Matrix viewProjMtx; viewProjMtx.setMul( activeCamera.getViewMtx(), activeCamera.getProjectionMtx() ); // activate the final render target new ( renderer() ) RCActivateRenderTarget( data.m_finalLightColorTarget ); // set and configure the pixel shader RCBindPixelShader* psComm = new ( renderer() ) RCBindPixelShader( *m_pixelShader, renderer ); { Matrix mtxInvProj; mtxInvProj.setInverse( activeCamera.getProjectionMtx() ); Vector lightOriginViewSpace; activeCamera.getViewMtx().transform( globalMtx.position(), lightOriginViewSpace ); Vector halfPixel; ShaderUtils::calculateHalfPixel( renderer, data.m_depthTex, halfPixel ); psComm->setVec4( "g_halfPixel", halfPixel ); psComm->setVec4( "g_lightOriginVS", lightOriginViewSpace ); psComm->setVec4( "g_lightColor", ( const Vector& )light->m_color ); psComm->setFloat( "g_strength", light->m_strength ); psComm->setFloat( "g_attenuation", light->m_attenuation ); psComm->setFloat( "g_radius", light->m_radius ); psComm->setFloat( "g_farZ", activeCamera.getFarClippingPlane() ); psComm->setMtx( "g_mtxProjToView", mtxInvProj ); psComm->setTexture( "g_Depth", data.m_depthTex ); psComm->setTexture( "g_Normals", data.m_normalsTex ); psComm->setTexture( "g_Specular", data.m_specularTex ); psComm->setTexture( "g_SceneColor", data.m_sceneColorTex ); psComm->setInt( "g_materialsTexSize", data.m_materialsDescriptorsTex->getWidth() ); psComm->setTexture( "g_MaterialIndices", data.m_materialIndicesTex ); psComm->setTexture( "g_MaterialsDescr", data.m_materialsDescriptorsTex ); } // set and configure the vertex shader RCBindVertexShader* vsComm = new ( renderer() ) RCBindVertexShader( *m_vertexShader, renderer ); { FastFloat rad; rad.setFromFloat( light->m_radius ); Matrix scaleMtx; scaleMtx.scaleUniform( rad ); Matrix modelViewProjMtx; modelViewProjMtx.setMul( scaleMtx, globalMtx ); modelViewProjMtx.mul( viewProjMtx ); vsComm->setMtx( "g_mtxModelViewProj", modelViewProjMtx ); } // draw the geometry m_pointLightMesh->render( renderer ); // cleanup new ( renderer() ) RCUnbindVertexShader( *m_vertexShader ); new ( renderer() ) RCUnbindPixelShader( *m_pixelShader, renderer ); new ( renderer() ) RCDeactivateRenderTarget(); }
void MeshUtils::calculateVertexTangents( const std::vector< Face >& faces, std::vector< LitVertex >& inOutVertices ) { /** * I used the algorithm from this page: http://www.terathon.com/code/tangent.html. */ uint vertexCount = inOutVertices.size(); Vector* tan1 = new Vector[vertexCount * 2]; Vector* tan2 = tan1 + vertexCount; memset( tan1, 0, vertexCount * sizeof(Vector) * 2 ); Vector sdir, tdir; uint trianglesCount = faces.size(); for ( uint i = 0; i < trianglesCount; ++i ) { const Face& tri = faces[i]; uint i1 = tri.idx[0]; uint i2 = tri.idx[1]; uint i3 = tri.idx[2]; const TVector<3>& v1 = inOutVertices[i1].m_coords; const TVector<3>& v2 = inOutVertices[i2].m_coords; const TVector<3>& v3 = inOutVertices[i3].m_coords; const TVector<2>& w1 = inOutVertices[i1].m_textureCoords; const TVector<2>& w2 = inOutVertices[i2].m_textureCoords; const TVector<2>& w3 = inOutVertices[i3].m_textureCoords; float x1 = v2[0] - v1[0]; float x2 = v3[0] - v1[0]; float y1 = v2[1] - v1[1]; float y2 = v3[1] - v1[1]; float z1 = v2[2] - v1[2]; float z2 = v3[2] - v1[2]; float s1 = w2[0] - w1[0]; float s2 = w3[0] - w1[0]; float t1 = w2[1] - w1[1]; float t2 = w3[1] - w1[1]; float r = (s1 * t2 - s2 * t1); if ( r != 0.0f ) { r = 1.0f / r; sdir.set( (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r ); tdir.set( (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r ); tan1[i1].add( sdir ); tan1[i2].add( sdir ); tan1[i3].add( sdir ); tan2[i1].add( tdir ); tan2[i2].add( tdir ); tan2[i3].add( tdir ); } } Vector vertexNorm, vertexTangent, normTanCross; for ( uint i = 0; i < vertexCount; ++i ) { vertexNorm.load( inOutVertices[i].m_normal ); const Vector& t = tan1[i]; // Gram-Schmidt orthogonalize FastFloat normTan1Dot; normTan1Dot.setNeg( vertexNorm.dot( t ) ); vertexTangent.setMulAdd( vertexNorm, normTan1Dot, t ); vertexTangent.normalize(); // Calculate handedness normTanCross.setCross( vertexNorm, t ); FastFloat handedness; handedness.setSign( normTanCross.dot( tan2[i] ) ); handedness.reciprocal(); vertexTangent.mul( handedness ); // store the results vertexTangent.store( inOutVertices[i].m_tangent ); } delete[] tan1; }
const FastFloat FastFloat::fromWord( word val ) { FastFloat f; f.setFromWord( val ); return f; }
const FastFloat FastFloat::fromByte( byte val ) { FastFloat f; f.setFromByte( val ); return f; }
const FastFloat FastFloat::fromInt( int val ) { FastFloat f; f.setFromInt( val ); return f; }
const FastFloat FastFloat::fromFloat( float val ) { FastFloat f; f.setFromFloat( val ); return f; }
TriangleMesh* DebugGeometryBuilder::createTorus( float innerRadius, float outerRadius, const Matrix& transform, int segmentsCount, int segmentVerticesCount ) { const Vector& origin = transform.position(); const Vector& mainAxis = transform.forwardVec(); const Vector& sideAxis = transform.sideVec(); Vector circumferenceAxis = transform.upVec(); FastFloat circumferenceWidth; circumferenceWidth.setFromFloat( outerRadius - innerRadius ); FastFloat radius; radius.setFromFloat( innerRadius + outerRadius - innerRadius ); // calculate torus vertices const uint verticesCount = segmentsCount * segmentVerticesCount; std::vector<LitVertex> vertices( verticesCount ); { FastFloat dMainAngle; dMainAngle.setFromFloat( DEG2RAD( 360.0f / (float)segmentsCount ) ); FastFloat dSegmentAngle; dSegmentAngle.setFromFloat( DEG2RAD( 360.0f / (float)segmentVerticesCount ) ); FastFloat mainAngle = Float_0; Quaternion mainRot, circumferenceRot; Vector vtxPos, posOnCircumference, radiusDisplacement, radiusVec, torusVtx; radiusVec.setMul( sideAxis, radius ); uint vtxIdx = 0; for ( uint segmentIdx = 0; segmentIdx < segmentsCount; ++segmentIdx, mainAngle.add( dMainAngle ) ) { mainRot.setAxisAngle( mainAxis, mainAngle ); mainRot.transform( radiusVec, radiusDisplacement ); FastFloat segmentAngle = Float_0; for ( uint segVtxIdx = 0; segVtxIdx < segmentVerticesCount; ++segVtxIdx, segmentAngle.add( dSegmentAngle ) ) { circumferenceRot.setAxisAngle( circumferenceAxis, segmentAngle ); Quaternion rotQ; rotQ.setMul( circumferenceRot, mainRot ); // first - create a point on the circumference of the toruses' segment vtxPos.setMul( sideAxis, circumferenceWidth ); rotQ.transform( vtxPos, posOnCircumference ); // and displace the circumference point so that it ends up in its final position on the toruses' circumference torusVtx.setAdd( radiusDisplacement, posOnCircumference ); torusVtx.add( origin ); // store the vertex torusVtx.store( vertices[vtxIdx].m_coords ); ++vtxIdx; } } } // set torus indices const uint outFacesCount = verticesCount * 2; std::vector<Face> outFaces( outFacesCount ); { uint faceIdx = 0; for ( uint segmentIdx = 0; segmentIdx < segmentsCount; ++segmentIdx ) { uint currSegmentFirstVtx = segmentIdx * segmentVerticesCount; uint nextSegmentFirstVtx = ( currSegmentFirstVtx + segmentVerticesCount ) % verticesCount; for ( uint segVtxIdx = 0; segVtxIdx < segmentVerticesCount; ++segVtxIdx ) { uint skipOffset = 0; if ( segVtxIdx == 0 ) { skipOffset = segmentVerticesCount; } outFaces[faceIdx].idx[0] = currSegmentFirstVtx + segVtxIdx - 1 + skipOffset; outFaces[faceIdx].idx[1] = currSegmentFirstVtx + segVtxIdx; outFaces[faceIdx].idx[2] = nextSegmentFirstVtx + segVtxIdx - 1 + skipOffset; ++faceIdx; outFaces[faceIdx].idx[0] = currSegmentFirstVtx + segVtxIdx; outFaces[faceIdx].idx[1] = nextSegmentFirstVtx + segVtxIdx; outFaces[faceIdx].idx[2] = nextSegmentFirstVtx + segVtxIdx - 1 + skipOffset; ++faceIdx; } } } TriangleMesh* mesh = new TriangleMesh( FilePath(), vertices, outFaces ); return mesh; }