Matrix BGE_NCP Matrix::SetLookAt(Vector4 BGE_NCP Position, Vector4 BGE_NCP Target, Vector4 BGE_NCP UpVector) { Vector4 Forward = Target - Position; Forward.Normalize(); Vector4 Side = Cross(Forward, UpVector); Side.Normalize(); Vector4 Up = Cross(Side, Forward); Up.Normalize(); Val[0] = Side[0]; Val[4] = Side[1]; Val[8] = Side[2]; Val[1] = Up[0]; Val[5] = Up[1]; Val[9] = Up[2]; Val[2] = -Forward[0]; Val[6] = -Forward[1]; Val[10] = -Forward[2]; Val[3] = Val[7] = Val[11] = 0; Val[12] = -Dot(Side, Position); Val[13] = -Dot(Up, Position); Val[14] = Dot(Forward, Position); return *this; }
Vector4 LightInfo::GetPointLightOnPoint(const Vector4& _cameraSpacePoint, const Vector4& _point, const Vector4& _normal, int _lightIndex, const Vector4& _diffuse, const Vector4& _specular) { // Get the difference in position from the light and the point. Vector4 diff = GetPointLights()[_lightIndex].GetPosition() - _point; Vector4 lightDirection = diff; // The distance float distance = diff.Length(); // The direction diff.Normalize(); // The attenuation float attenuation = GetPointLights()[_lightIndex].GetAttenuation(distance); // Diffuse lighting. Vector4 pointColor = GetPointLights()[_lightIndex].GetIntensity() * diff.Dot(_normal) * attenuation * _diffuse; pointColor.Clamp(); // Specular // We get the half angle between the camera and the direction to the camera. Vector4 halfAngle = lightDirection + _cameraSpacePoint; halfAngle.Normalize(); Vector4 specular = _specular * powf(halfAngle.Dot(_normal), 10) * attenuation; specular.Clamp(); pointColor += specular; return pointColor; }
void CSDFController::ComputeTNB(Face* tmp, Vector4& tang, Vector4& norm, Vector4& binor) { // compute tanget space matrix Vector4 U = Vector4(tmp->v[1]->P - tmp->v[0]->P); Vector4 V = Vector4(tmp->v[2]->P - tmp->v[0]->P); norm = (U % V) * (-1.0); norm.Normalize(); tang = Vector4(tmp->v[0]->P - tmp->v[2]->P); tang.Normalize(); binor = tang % norm; binor.Normalize(); }
void Camera::BuildViewMatrix(const Maths::Vector4 &position, const Maths::Vector4 &lookAt, const Maths::Vector4 &up) { Vector4 viewDir = lookAt - position; Vector4 viewSide, viewUp; // store values m_up = up; m_position = position; m_lookAt = lookAt; viewDir.Normalize(); viewUp = up - viewDir * up.DotProduct( viewDir ); viewUp.Normalize(); viewSide = viewDir.CrossProduct( viewUp ); // setup inverse rotation matrix Matrix4 rotation; rotation.SetRows( viewSide, viewUp, Vector4( -viewDir.X, -viewDir.Y, -viewDir.Z, -viewDir.W ), Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ); //transform translation Vector4 invPos; Matrix4::Transform( rotation, position, invPos ); m_inversePosition = -invPos; // build view matrix Matrix4 view; Matrix4::Multiply( view, rotation, m_viewMatrix ); m_viewMatrix( 0, 3 ) = m_inversePosition.X; m_viewMatrix( 1, 3 ) = m_inversePosition.Y; m_viewMatrix( 2, 3 ) = m_inversePosition.Z; m_viewMatrix( 3, 3 ) = m_inversePosition.W; m_viewDir = viewDir; }
/* Random */ Vector4 Random(void) { int x = rand() - rand(); int y = rand() - rand(); int z = rand() - rand(); // z = 0 for now until graphics issues sorted out Vector4 toReturn = Vector4(x, y, 0); toReturn.Normalize(); return toReturn; }
/* Get the light value for a point in space */ Vector4 LightInfo::GetDirectionalLightOnPoint(const Vector4& _cameraSpacePoint, const Vector4& _normal, int _lightIndex, const Vector4& _diffuse, const Vector4& _specular) { Vector4 directionalColor = GetDirectionalLights()[_lightIndex].GetIntensity() * GetDirectionalLights()[_lightIndex].GetDirection().Dot(_normal) * _diffuse; directionalColor.Clamp(); // Specular Vector4 halfAngle = GetDirectionalLights()[_lightIndex].GetDirection() + _cameraSpacePoint; halfAngle.Normalize(); Vector4 specular = _specular * powf(halfAngle.Dot(_normal), 100) * GetDirectionalLights()[_lightIndex].GetIntensity(); specular.Clamp(); directionalColor += specular; return directionalColor; }
// Get the spot light info on a point. Vector4 LightInfo::GetSpotLightOnPoint(const Vector4& _cameraSpacePoint, const Vector4& _point, const Vector4& _normal, int _lightIndex, const Vector4& _diffuse, const Vector4& _specular) { // Get the difference in position from the light and the point. Vector4 diff = GetSpotLights()[_lightIndex].GetPosition() - _point; Vector4 lightDirection = diff; // The distance float distance = diff.Length(); // The direction diff.Normalize(); // Calculate the spot light values float spotLightValue = diff.Dot(GetSpotLights()[_lightIndex].GetDirection() * -1); if (spotLightValue > 0.2f) return Vector4(0, 0, 0, 0); float smoothing = GetSpotLights()[_lightIndex].SmoothStep(diff.Dot(_normal)); // The attenuation float attenuation = GetSpotLights()[_lightIndex].GetAttenuation(distance); // Diffuse lighting. Vector4 pointColor = GetSpotLights()[_lightIndex].GetIntensity() * diff.Dot(_normal) * attenuation * _diffuse * spotLightValue; // Specular // We get the half angle between the camera and the direction to the camera. Vector4 halfAngle = lightDirection + _cameraSpacePoint; halfAngle.Normalize(); pointColor += _specular * powf(halfAngle.Dot(_normal), 10) * attenuation; return pointColor; }
void Shader::BindLight(const std::shared_ptr<SceneNode> &lightNode) { Vector4 lightPos = lightNode->GetWorldPosition(); Vector4 lightDir = lightNode->GetWorldMatrix().Multiply(Vector4(0, -1, 0, 0)); lightDir.Normalize(); if (auto light = lightNode->GetComponent<Light>()) { Color color = light->GetColor(); BindFloat("light_pos", lightPos.x, lightPos.y, lightPos.z); BindFloat("light_dir", lightDir.x, lightDir.y, lightDir.z); BindFloat("light_color", color.r, color.g, color.b); BindFloat("light_intensity", light->GetIntensity()); BindFloat("light_innerangle", light->GetInnerAngle()); BindFloat("light_outterangle", light->GetOutterAngle()); BindFloat("light_falloff", light->GetFalloff()); BindFloat("light_radius", light->GetRadius()); } }
Matrix4 Matrix4::GetRotate(const Vector4& from, const Vector4& to) { Vector4 axis = from.Cross(to); axis.Normalize(); float degrees = from.GetAngleBetween(to); return GetRotate(degrees, axis); }
// pocitanie funkcie pre vsetky trojuholniky, O(n2) void CSDFController::Compute(LinkedList<Face>* triangles, Octree* root) { float min = FLOAT_MAX; float max = 0.0; unsigned int n_rays = 30; float angle = 120.0f; unsigned int counter = 0; //------------------prealocated variables------------------ Vector4 tangens, normal, binormal; Mat4 t_mat; std::vector<float> rays; std::vector<float> weights; // precompute those N rays srand (123); // initial seed for random number generator float* rndy = new float[n_rays]; float* rndx = new float[n_rays]; for(unsigned int i = 0; i < n_rays; i++) { rndy[i] = float(rand()%int(angle / 2)); rndx[i] = float(rand()%(360)); if(rndy[i] == 0.0) rndy[i] = 0.5; } float dist = FLOAT_MAX; float dist2 = FLOAT_MAX; float theta = 0.0f; bool intersected = false; LinkedList<Face>* face_list = NULL; LinkedList<Face>::Cell<Face>* intersected_face = NULL; //------------------prealocated variables------------------ LinkedList<Face>::Cell<Face>* current_face = triangles->start; while(current_face != NULL) { // vypocet TNB vektorov a matice ComputeTNB(current_face->data, tangens, normal, binormal); t_mat = Mat4(tangens, normal, binormal); rays.clear(); weights.clear(); for(unsigned int i = 0; i < n_rays; i++) { Vector4 ray = CalcRayFromAngle(rndx[i], rndy[i]) * t_mat; ray.Normalize(); dist = FLOAT_MAX; face_list = GetFaceList(triangles, root, current_face->data->center, ray); intersected_face = face_list->start; while(intersected_face != NULL) { if(current_face == intersected_face) { intersected_face = intersected_face->next; continue; } dist2 = FLOAT_MAX; intersected = rayIntersectsTriangle(current_face->data->center, ray, intersected_face->data->v[0]->P, intersected_face->data->v[1]->P, intersected_face->data->v[2]->P, dist2); if(intersected == true) { theta = acos( (ray * intersected_face->data->normal) / (ray.Length() * intersected_face->data->normal.Length()) ); theta = theta * float(180.0 / M_PI); //loggger->logInfo(MarshalString("pridany ray s thetou: " + theta)); if((theta < 90.0f) && (dist2 < dist)) dist = dist2; } intersected_face = intersected_face->next; } if(dist < (FLOAT_MAX - 1.0f)) { //loggger->logInfo(MarshalString("pridany ray s dlzkou: " + dist)); rays.push_back(dist); weights.push_back(180.0f - rndy[i]); } //if(root != NULL) //delete face_list; // generated list, bez prealokovania } if(rays.size() > 0) { current_face->data->ComputeSDFValue(rays, weights); if(current_face->data->diameter->value < min) min = current_face->data->diameter->value; if(current_face->data->diameter->value > max) max = current_face->data->diameter->value; } counter = counter + 1; current_face = current_face->next; } fc_list->Clear(); oc_list->Clear(); delete [] rndy; delete [] rndx; // postprocessing - smoothing and normalization //float kernel[] = {1.0,4.0,6.0,4.0,1.0}; float* kernel = ComputeGaussianKernel(kernel_size); current_face = triangles->start; while(current_face != NULL) { Smooth(current_face->data, kernel, kernel_size); current_face->data->diameter->Normalize1(min, max, 4.0); current_face->data->diameter->Normalize2(0, max, 4.0); //tmp->data->diameter->Normalize2(0, diagonal, 4.0); current_face = current_face->next; } delete kernel; }
void Mesh::CalculateLightingPoint( const std::vector<LightPoint>& light, int numLight, const Maths::Vector4& camera) { Maths::Vector4 l; Maths::Vector4 temp, result, n, p; Maths::Vector4 cof( 1.0f, 1.0f, 10.0f ); BYTE r, g, b; float distance = 0; float att = 0; float a = 0.05f; float bb = 0.05f; float c = 0.05f; float dif, spec; m_noLight = false; for ( int i = 0; i < m_numVerts; ++i ) { if ( !m_transformed[i].IsCulled ) { result.X = 0; //Red result.Y = 0; //green result.Z = 0; //blue for ( int j = 0; j < numLight; ++j ) { p = light[j].Position; l = p - m_transformed[i].Position; distance = l.Length(); //calculate the attenuation value att = 1 / (a + ( distance * bb ) + ( distance * distance ) * c ); if ( att < 0 ) att = 0; temp.X = light[j].Colour.GetR(); temp.Y = light[j].Colour.GetG(); temp.Z = light[j].Colour.GetB(); n = m_transformed[i].Normal; n.Normalize(); dif = max( 0.0, l.DotProduct( n ) ) * att; // calculate the speculation //Vector4 toEye = m_transformed[i].Position - camera; //Vector4 half = camera + p / 2; //toEye.Normalize(); //half.Normalize(); //float specPower = 1.0f; //float spec = pow( max( n.DotProduct( half ), 0.0f ), specPower ) * att; Vector4 toEye = m_transformed[i].Position - camera; Vector4 reflect = ( n - l ) * ( 2 * ( n.DotProduct( l ) ) ); toEye.Normalize(); reflect.Normalize(); float specPower = 1.0f; float spec = pow( max( reflect.DotProduct( toEye ), 0.0f ), specPower ) * att; temp.X = temp.X * ( (dif + spec) * m_kd_red ); temp.Y = temp.Y * ( (dif + spec) * m_kd_green ); temp.Z = temp.Z * ( (dif + spec) * m_kd_blue ); //temp.X = temp.X * ( dif * m_kd_red ) ); //temp.Y = temp.Y * ( dif * m_kd_green ) ); //temp.Z = temp.Z * ( dif * m_kd_blue ) ); result += temp; } //set colour if ( result.X > 255.0f ) result.X = 255.0f; if ( result.Y > 255.0f ) result.Y = 255.0f; if ( result.Z > 255.0f ) result.Z = 255.0f; if ( result.X < 0.0f ) result.X = 0.0f; if ( result.Y < 0.0f ) result.Y = 0.0f; if ( result.Z < 0.0f ) result.Z = 0.0f; r = (BYTE)result.X; g = (BYTE)result.Y; b = (BYTE)result.Z; m_transformed[i].Colour = Gdiplus::Color::MakeARGB( 255, r, g, b ); } } }
void Mesh::CalculateLightingDirectional(const LightDirectional& light, int numLights, const Vector4& camera) { Maths::Vector4 total; Maths::Vector4 temp; Maths::Vector4 l( light.Position.X, light.Position.Y, light.Position.Z, 1.0f ); Maths::Vector4 n( 0, 0, 0, 0 ); BYTE r, g, b; float diff, spec = 0; m_noLight = false; l.Normalize(); for ( int i = 0; i < m_numVerts; ++i ) { if ( !m_transformed[i].IsCulled ) { //reset the colout to black total.X = 0; //Red total.Y = 0; //green total.Z = 0; //blue for ( int j = 0; j < numLights; ++j ) { Maths::Vector4 d; //modulate intensity with coresponding reflectance co-efficient values temp.X = light.Colour.GetR() * light.Intensity.X; temp.Y = light.Colour.GetG() * light.Intensity.Y; temp.Z = light.Colour.GetB() * light.Intensity.Z; n = m_transformed[i].Normal; n.Normalize(); //attentuate the rgb values with lambertian attenuation diff = max(0.0, l.DotProduct( n )); Vector4 toEye = m_transformed[i].Position - camera; Vector4 reflect = ( n - l ) * ( 2 * ( n.DotProduct( l ) ) ); toEye.Normalize(); reflect.Normalize(); float specPower = 1.0f; spec = pow( max( reflect.DotProduct( toEye ), 0.0f ), specPower ) * 0.01f; if ( diff <= 0.0f ) spec = 0.0f; temp.X = temp.X * ( (diff + spec) * m_kd_red ); temp.Y = temp.Y * ( (diff + spec) * m_kd_green ); temp.Z = temp.Z * ( (diff + spec) * m_kd_blue ); //temp.X = temp.X * ( diff * m_kd_red + spec ) ); //temp.Y = temp.Y * ( diff * m_kd_green + spec ) ); //temp.Z = temp.Z * ( diff * m_kd_blue + spec ) ); total = total + temp; } if ( total.X > 255.0f ) total.X = 255.0f; if ( total.Y > 255.0f ) total.Y = 255.0f; if ( total.Z > 255.0f ) total.Z = 255.0f; if ( total.X < 0.0f ) total.X = 0.0f; if ( total.Y < 0.0f ) total.Y = 0.0f; if ( total.Z < 0.0f ) total.Z = 0.0f; r = (BYTE)total.X; g = (BYTE)total.Y; b = (BYTE)total.Z; m_transformed[i].Colour = Gdiplus::Color::MakeARGB( 255, r, g, b ); } } }
void Mesh::CalculateFlatLightingPoint(const std::vector<LightPoint>& light, int numLights, const Vector4& camera) { Maths::Vector4 l; Maths::Vector4 temp, result, n, p; BYTE r, g, b; float distance = 0; float att = 0; float a = 0.05f; float bb = 0.05f; float c = 0.05f; float dif, spec; m_noLight = false; for ( int i = 0; i < m_numPolys; ++i ) { result.X = 0; //Red result.Y = 0; //green result.Z = 0; //blue if ( !m_polys[i].IsCulled ) { for ( int j = 0; j < numLights; ++j ) { //get the position of the light and calculate the //distance between the object and the lifght p = light[j].Position; l = p - m_transformed[ m_polys[i].Indices[0] ].Position; distance = l.Length(); //calculate the attenuation value att = 1 / (a + ( distance * bb ) + ( distance * distance ) * c ); if ( att < 0) att = 0; temp.X = light[j].Colour.GetR(); temp.Y = light[j].Colour.GetG(); temp.Z = light[j].Colour.GetB(); // get the normalized value of the polygon normals //n = m_polys[i]._normalN; //n.Normalize(); // calculate the diffuse value dif = max( l.DotProduct( m_polys[i].NormalN ), 0.0f ) * att; // multiply dif with materials // calculate the speculation //Vector4 toEye = m_transformed[ m_polys[i]._indices[0] ]._position - camera; //Vector4 reflect = ( n - l ) * ( 2 * ( n.DotProduct( l ) ) ); //toEye.Normalize(); //reflect.Normalize(); //float specPower = 1.0f; //float spec = pow( max( reflect.DotProduct( toEye ), 0.0f ), specPower ) * att; Vector4 toEye = m_transformed[ m_polys[i].Indices[0] ].Position - camera; Vector4 half = camera + p / 2; toEye.Normalize(); half.Normalize(); float specPower = 1.0f; float spec = pow( max( n.DotProduct( half ), 0.0f ), specPower ) * att; temp.X = temp.X * ( (dif + spec) * m_kd_red ); temp.Y = temp.Y * ( (dif + spec) * m_kd_green ); temp.Z = temp.Z * ( (dif + spec) * m_kd_blue ); result += temp; } //set colour if ( result.X > 255.0f ) result.X = 255; if ( result.Y > 255.0f ) result.Y = 255; if ( result.Z > 255.0f ) result.Z = 255; if ( result.X < 0.0f ) result.X = 0; if ( result.Y < 0.0f ) result.Y = 0; if ( result.Z < 0.0f ) result.Z = 0; r = (BYTE)result.X; g = (BYTE)result.Y; b = (BYTE)result.Z; m_polys[i].Colour = Gdiplus::Color::MakeARGB( 255, r, g, b ); } } }
void Mesh::CalculateFlatLightingDirectional(const LightDirectional &light, int numLights, const Vector4& cameraPos, const Matrix4& view) { Maths::Vector4 total, temp; Maths::Vector4 reflect; Maths::Vector4 v = cameraPos; Maths::Vector4 l( light.Position.X, light.Position.Y, light.Position.Z, 1.0f ); Maths::Vector4 n( 0, 0, 0 ); Maths::Vector4 t, halfWay; BYTE r, g, b; float spec = 0; float diff = 0; float ave = 0; m_noLight = false; //workout the "halfway" vector for specularity ave = v.Length(); //halfWay = ( v + l ) / ave; //halfWay.Normalize(); //normalize the light position l.Normalize(); for ( int i = 0; i < m_numPolys; ++i ) { if ( !m_polys[i].IsCulled ) { //reset the colout to black total.X = 0; //Red total.Y = 0; //green total.Z = 0; //blue for ( int j = 0; j < numLights; ++j ) { //store intensity to corresponding variables //modulate intensity with coresponding reflectance co-efficient values temp.X = light.Colour.GetR() * light.Intensity.X; temp.Y = light.Colour.GetG() * light.Intensity.Y; temp.Z = light.Colour.GetB() * light.Intensity.Z; //reflect = ( 2 * ( m_polys[i]._normal.DotProduct( light._position ) ) * ( m_polys[i]._normal - light ); n.SetValues( m_polys[i].Normal.X, m_polys[i].Normal.Y, m_polys[i].Normal.Z, 1.0f ); n.Normalize(); //attentuate the rgb values with lambertian attenuation diff = max( 0.0f, l.DotProduct( n ) ); //calculate specular coponent Vector4 toEye; Matrix4::Transform( view, m_transformed[ m_polys[i].Indices[0] ].Position, toEye ); toEye.Normalize(); float r = max( 0, m_transformed[ m_polys[i].Indices[0] ].Normal.DotProduct( l ) ); Vector4 reflect = m_transformed[ m_polys[i].Indices[0] ].Normal; reflect.Multiply( 2 * r ); reflect.Subtract( l ); //Vector4 toEye = m_transformed[ m_polys[i]._indices[0] ]._position - viewer; //Vector4 reflect = ( n - l ) * ( 2 * ( n.DotProduct( l ) ) ); toEye.Normalize(); reflect.Normalize(); float specPower = 1.0f; float spec = 0; //max( 0, pow( max( 0.0f, reflect.DotProduct( toEye ) ), specPower ) ) * m_specular; if ( diff <= 0.0f ) spec = 0.0f; temp.X = temp.X * ( (diff + spec) * m_kd_red ); temp.Y = temp.Y * ( (diff + spec) * m_kd_green ); temp.Z = temp.Z * ( (diff + spec) * m_kd_blue ); total = total + temp; } //clamp the values if (total.X > 255) total.X = 255; if (total.Y > 255) total.Y = 255; if (total.Z > 255) total.Z = 255; if (total.X < 0) total.X = 0; if (total.Y < 0) total.Y = 0; if (total.Z < 0) total.Z = 0; r = (BYTE)total.X; g = (BYTE)total.Y; b = (BYTE)total.Z; m_polys[i].Colour = Gdiplus::Color::MakeARGB(255, r, g, b); } } }
Void Mesh::Transform( const Transform3 & vModelTransform, GPUDeferredContext * pContext ) { Assert( m_pIL != NULL && m_pVB != NULL ); Assert( m_pIL->IsBound() && m_pVB->IsBound() ); if ( vModelTransform.IsIdentity() ) return; // Begin update Byte * pFirstVertex = NULL; if ( m_pVB->CanUpdate() ) { Assert( m_pVB->HasCPUData() ); pFirstVertex = m_pVB->GetData( m_iVertexOffset ); } else { Assert( m_pVB->CanLock() ); UInt iByteSize = 0; pFirstVertex = (Byte*)( m_pVB->Lock( GPURESOURCE_LOCK_WRITE, 0, &iByteSize, pContext ) ); Assert( iByteSize == m_pVB->GetSize() ); } // Transform VB UInt iVertexSize = m_pVB->GetElementSize(); UInt iOffset, iSize; Byte * arrPositions = NULL; Byte * arrNormals = NULL; Byte * arrTangents = NULL; Byte * arrBiNormals = NULL; m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_POSITION, 0 ); arrPositions = ( pFirstVertex + iOffset ); if ( m_pIL->HasField(GPUINPUTFIELD_SEMANTIC_NORMAL, 0) ) { m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_NORMAL, 0 ); arrNormals = ( pFirstVertex + iOffset ); } if ( m_pIL->HasField(GPUINPUTFIELD_SEMANTIC_TANGENT, 0) ) { m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_TANGENT, 0 ); arrTangents = ( pFirstVertex + iOffset ); } if ( m_pIL->HasField(GPUINPUTFIELD_SEMANTIC_BINORMAL, 0) ) { m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_BINORMAL, 0 ); arrTangents = ( pFirstVertex + iOffset ); } Vertex4 * pPosition; Vector4 * pNormal; Vector4 * pTangent; Vector4 * pBiNormal; for( UInt i = 0; i < m_iVertexCount; ++i ) { pPosition = (Vertex4*)( arrPositions ); *pPosition = ( vModelTransform * (*pPosition) ); arrPositions += iVertexSize; if ( arrNormals != NULL ) { pNormal = (Vector4*)( arrNormals ); *pNormal = ( vModelTransform * (*pNormal) ); pNormal->Normalize(); arrNormals += iVertexSize; } if ( arrTangents != NULL ) { pTangent = (Vector4*)( arrTangents ); *pTangent = ( vModelTransform * (*pTangent) ); pTangent->Normalize(); arrTangents += iVertexSize; } if ( arrBiNormals != NULL ) { pBiNormal = (Vector4*)( arrBiNormals ); *pBiNormal = ( vModelTransform * (*pBiNormal) ); pBiNormal->Normalize(); arrBiNormals += iVertexSize; } } // End update if ( m_pVB->CanUpdate() ) m_pVB->Update( 0, INVALID_OFFSET, pContext ); else m_pVB->UnLock( pContext ); }
Void TriangleMesh::UpdateNormals( GPUDeferredContext * pContext ) { Assert( m_pIL != NULL && m_pVB != NULL ); Assert( m_pIL->IsBound() && m_pVB->IsBound() ); Bool bHasNormals = m_pIL->HasField( GPUINPUTFIELD_SEMANTIC_NORMAL, 0 ); if ( !bHasNormals ) return; // Begin update Byte * pFirstVertex = NULL; if ( m_pVB->CanUpdate() ) { Assert( m_pVB->HasCPUData() ); pFirstVertex = m_pVB->GetData( m_iVertexOffset ); } else { Assert( m_pVB->CanLock() ); UInt iByteSize = 0; pFirstVertex = (Byte*)( m_pVB->Lock( GPURESOURCE_LOCK_WRITE, 0, &iByteSize, pContext ) ); Assert( iByteSize == m_pVB->GetSize() ); } // Update normals UInt iVertexSize = m_pVB->GetElementSize(); UInt iOffset, iSize; const Byte * arrPositions = NULL; Byte * arrNormals = NULL; m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_POSITION, 0 ); arrPositions = ( pFirstVertex + iOffset ); m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_NORMAL, 0 ); arrNormals = ( pFirstVertex + iOffset ); UInt i, iTriangleCount = GetTriangleCount(); // Set all normals to null vector Byte * pCurNormal = arrNormals; Vector4 * pNormal; for( i = 0; i < m_iVertexCount; ++i ) { pNormal = (Vector4*)pCurNormal; pNormal->X = 0.0f; pNormal->Y = 0.0f; pNormal->Z = 0.0f; pCurNormal += iVertexSize; } // Weighted sum of facet normals UInt iA, iB, iC; const Vertex4 *pA, *pB, *pC; Vector4 vAB, vAC, vFaceNormal; for( i = 0; i < iTriangleCount; ++i ) { GetTriangle( i, iA, iB, iC ); iA *= iVertexSize; iB *= iVertexSize; iC *= iVertexSize; pA = (const Vertex4 *)( arrPositions + iA ); pB = (const Vertex4 *)( arrPositions + iB ); pC = (const Vertex4 *)( arrPositions + iC ); vAB = ( *pB - *pA ); vAC = ( *pC - *pA ); vFaceNormal = ( vAB ^ vAC ); vFaceNormal.Normalize(); pNormal = (Vector4*)( arrNormals + iA ); *pNormal += vFaceNormal; pNormal = (Vector4*)( arrNormals + iB ); *pNormal += vFaceNormal; pNormal = (Vector4*)( arrNormals + iC ); *pNormal += vFaceNormal; } // Normalize all again pCurNormal = arrNormals; for( i = 0; i < m_iVertexCount; ++i ) { pNormal = (Vector4*)pCurNormal; pNormal->Normalize(); pCurNormal += iVertexSize; } // End update if ( m_pVB->CanUpdate() ) m_pVB->Update( 0, INVALID_OFFSET, pContext ); else m_pVB->UnLock( pContext ); }
/* Normalize */ Vector4 Normalize(Vector4 toNorm) { toNorm.Normalize(); return toNorm; }
Vector4 Vector4::Normalize( Vector4 vector ) { vector.Normalize(); return vector; }