static void PlaceDetail( DetailModel_t const& model, const Vector& pt, const Vector& normal ) { // But only place it on the surface if it meets the angle constraints... float cosAngle = normal.z; // Never emit if the angle's too steep if (cosAngle < model.m_MaxCosAngle) return; // If it's between min + max, flip a coin... if (cosAngle < model.m_MinCosAngle) { float probability = (cosAngle - model.m_MaxCosAngle) / (model.m_MinCosAngle - model.m_MaxCosAngle); float t = rand() / (float)RAND_MAX; if (t > probability) return; } // Compute the orientation of the detail QAngle angles; if (model.m_Flags & MODELFLAG_UPRIGHT) { // If it's upright, we just select a random yaw angles.Init( 0, 360.0f * rand() / (float)RAND_MAX, 0.0f ); } else { // It's not upright, so it must conform to the ground. Choose // a random orientation based on the surface normal Vector zaxis; VectorCopy( normal, zaxis ); // Choose any two arbitrary axes which are perpendicular to the normal Vector xaxis( 1, 0, 0 ); if (fabs(xaxis.Dot(zaxis)) - 1.0 > -1e-3) xaxis.Init( 0, 1, 0 ); Vector yaxis; CrossProduct( zaxis, xaxis, yaxis ); CrossProduct( yaxis, zaxis, xaxis ); VMatrix matrix; matrix.SetBasisVectors( xaxis, yaxis, zaxis ); float rotAngle = 360.0f * rand() / (float)RAND_MAX; VMatrix rot = SetupMatrixAxisRot( Vector( 0, 0, 1 ), rotAngle ); matrix = matrix * rot; MatrixToAngles( matrix, angles ); } // FIXME: We may also want a purely random rotation too // Insert an element into the object dictionary if it aint there... switch ( model.m_Type ) { case DETAIL_PROP_TYPE_MODEL: AddDetailToLump( model.m_ModelName.String(), pt, angles, model.m_Orientation ); break; case DETAIL_PROP_TYPE_SPRITE: { float flScale = 1.0f; if ( model.m_flRandomScaleStdDev != 0.0f ) { flScale = fabs( RandomGaussianFloat( 1.0f, model.m_flRandomScaleStdDev ) ); } AddDetailSpriteToLump( pt, angles, model.m_Orientation, model.m_Pos, model.m_Tex, flScale ); } break; } }
//----------------------------------------------------------------------------- // Copies the texture coordinate system from pFrom into pTo. Then it rotates // the texture around the edge until it's as close to pTo's normal as possible. //----------------------------------------------------------------------------- void CFaceEditMaterialPage::CopyTCoordSystem( const CMapFace *pFrom, CMapFace *pTo ) { Vector axis[2], vEdge, vEdgePt, vOrigin; Vector vFromPt, vNextFromPt; Vector vToPt, vPrevToPt; Vector vTestTextureNormal, vTextureNormal; VMatrix mEdgeRotation, mOriginRotation, mTranslation; float fAngle, fDot; bool bRotate; float fShift[2]; Vector vProjTexNormal; Vector vProjPolyNormal; // The edge vector lies on both planes. vEdge = pFrom->plane.normal.Cross(pTo->plane.normal); VectorNormalize( vEdge ); // To find a point on the plane, we make a plane from the edge vector and find the intersection // between the three planes (without the third plane, there are an infinite number of solutions). if( PlaneIntersection( VPlane(pFrom->plane.normal, pFrom->plane.dist), VPlane(pTo->plane.normal, pTo->plane.dist), VPlane(vEdge, 0.0f), vEdgePt ) ) { bRotate = true; } else { // Ok, in this case, the planes are parallel so we don't need to rotate around the edge anyway! bRotate = false; } // Copy the texture coordinate system. axis[0] = pFrom->texture.UAxis.AsVector3D(); axis[1] = pFrom->texture.VAxis.AsVector3D(); fShift[0] = pFrom->texture.UAxis[3]; fShift[1] = pFrom->texture.VAxis[3]; vOrigin = axis[0]*fShift[0]*pFrom->texture.scale[0] + axis[1]*fShift[1]*pFrom->texture.scale[1]; vTextureNormal = axis[0].Cross(axis[1]); VectorNormalize(vTextureNormal); if(bRotate) { // Project texture normal and poly normal into the plane of rotation // to get the angle between them. vProjTexNormal = vTextureNormal - vEdge * vEdge.Dot(vTextureNormal); vProjPolyNormal = pTo->plane.normal - vEdge * vEdge.Dot(pTo->plane.normal); VectorNormalize( vProjTexNormal ); VectorNormalize( vProjPolyNormal ); fDot = vProjTexNormal.Dot(vProjPolyNormal); fAngle = (float)(acos(fDot) * (180.0f / M_PI)); if(fDot < 0.0f) fAngle = 180.0f - fAngle; // Ok, rotate them for the final values. mEdgeRotation = SetupMatrixAxisRot(vEdge, fAngle); axis[0] = mEdgeRotation.ApplyRotation(axis[0]); axis[1] = mEdgeRotation.ApplyRotation(axis[1]); // Origin needs translation and rotation to rotate around the edge. mTranslation = SetupMatrixTranslation(vEdgePt); mOriginRotation = ~mTranslation * mEdgeRotation * mTranslation; vOrigin = mOriginRotation * vOrigin; } pTo->texture.UAxis.AsVector3D() = axis[0]; pTo->texture.VAxis.AsVector3D() = axis[1]; pTo->texture.UAxis[3] = axis[0].Dot(vOrigin) / pFrom->texture.scale[0]; pTo->texture.VAxis[3] = axis[1].Dot(vOrigin) / pFrom->texture.scale[1]; pTo->NormalizeTextureShifts(); pTo->texture.scale[0] = pFrom->texture.scale[0]; pTo->texture.scale[1] = pFrom->texture.scale[1]; // rotate is only for UI purposes, it doesn't actually do anything. pTo->texture.rotate = 0.0f; pTo->CalcTextureCoords(); }
VMatrix rotationMatrix; VMatrix invRotationMatrix; Vector transformedEye; float angle = 0.0f; if(sv_surface_rotate.GetBool()) { angle = view->GetViewSetup()->angles.y+180.0f; //ConMsg("Angle = %f\n", angle); pRenderContext->Rotate(angle, 0.0f, 0.0f, 1.0f); //VMatrix rotationMatrix2 = SetupMatrixAngles(view->GetViewSetup()->angles); //pRenderContext->MultMatrix(rotationMatrix2); //VMatrix rotationMatrix = rotationMatrix2.InverseTR(); //SetupMatrixAngles(-(view->GetViewSetup()->angles)); rotationMatrix = SetupMatrixAxisRot(Vector(0.0f, 0.0f, 1.0f), -angle); invRotationMatrix = SetupMatrixAxisRot(Vector(0.0f, 0.0f, 1.0f), angle); Vector eye = view->GetViewSetup()->origin; transformedEye = (eye-center)*(1.0f/m_flRadius); transformedEye = rotationMatrix.ApplyRotation(transformedEye); } else { rotationMatrix.Identity(); invRotationMatrix.Identity(); transformedEye.Init(); angle = 0.0f; } if(sv_surface_use_tiler.GetBool()) {
static int vmatrix_SetupMatrixAxisRot (lua_State *L) { lua_pushvmatrix(L, SetupMatrixAxisRot(luaL_checkvector(L, 1), luaL_checknumber(L, 2))); return 1; }