Page 1 of 2 12 LastLast
Results 1 to 10 of 19

Thread: Mathematics functions

  1. #1
    Developer
    Join Date
    Jun 2010
    Location
    Hungary
    Posts
    291

    Default Mathematics functions

    Is it possible to add new maths functions? I mean sinus, cosinus, tangent, arcsin, arccos, arctg, square and cube root.

  2. #2

    Default

    it I remember right there are already used here:
    http://www.modtheater.com/forum/show...rotating+doors
    :)

  3. #3
    Developer Sor's Avatar
    Join Date
    Aug 2010
    Location
    The Medieval City of Bruges
    Posts
    747

    Default

    Jv already did:
    Code:
    main:
    
    	level.PI = 3.1415926
    	//level.PI = 3.14159
    end
    // sin(x), x in rad
     // sin(x), x in rad
    sin local.x:
    end (waitthread cos(local.x - 0.5 * level.PI))
    
    // cos(x), x in rad
    cos local.x:
    	// reduce to [0,2pi]
    	if(local.x > 2.0 * level.PI)
    	{
    	  local.x -= (int (local.x / (2.0 * level.PI))) * 2.0 * level.PI
    	}
    	else if(local.x < 0.0)
    	{
    	  local.x += ((int ( -local.x / (2.0 * level.PI))) + 1) * 2.0 * level.PI
    	}   
    
    	// reduce to [-pi,pi]
    	if(local.x > level.PI)
    	{
    	  local.x -= 2.0 * level.PI
    	}
    
    	local.x2 = local.x * local.x
    	local.x4 = local.x2 * local.x2
    	local.x6 = local.x4 * local.x2
    	local.x8 = local.x6 * local.x2
    
    	// taylor series expansion
    	local.cosx = 1.0 - 0.5 * local.x2 + 0.04167 * local.x4 - 0.00139 * local.x6 + 0.00002 * local.x8
    
    	if(local.cosx < -1.0)
    	{
    	  local.cosx = -1.0
    	}
    	else if(local.cosx > 1.0)
    	{
    	  local.cosx = 1.0
    	}
    
    end local.cosx
    
    // tan(x), x in rad, undefined for x = (1/2 + k) * PI with k arbitrary int
    tan local.x:
    end ((waitthread sin local.x) / (waitthread cos local.x))
    
    
    
    // transforms vectors to angles (pitch,yaw,roll)
    // unlike vector_toangles this also includes roll
    vectors_toangles local.vec_fwd local.vec_lf:
       local.base_angles = vector_toangles local.vec_fwd
       
       local.base_fwd = local.vec_fwd
       local.base_lf = -1.0 * (angles_toleft local.base_angles)
       local.base_up = vector_cross local.base_fwd local.base_lf
       
       local.cos = local.vec_lf * local.base_lf
       
       if(abs local.cos < 0.8)
       {
          local.roll_angle = waitthread arccos local.cos
          
          if(local.vec_lf * local.base_up < 0.0)
          {
             local.roll_angle = -local.roll_angle
          }
       }
       else
       {
          // arccos inaccurate here
          // so just use arcsin instead
          // (far more sensitive in this region)
          local.sin = local.vec_lf * local.base_up
          
          local.roll_angle = waitthread arcsin local.sin
          
          if(local.cos < 0.0)
          {
             local.roll_angle = level.PI - local.roll_angle
          }
       }
       
       // convert to degrees
       local.roll_angle = local.roll_angle / level.PI * 180.0
       
       local.angles = local.base_angles
       local.angles[2] = local.roll_angle
    end local.angles
    
    // inverse sin
    // somewhat inaccurate near +-0.5PI
    arcsin local.x:
       if(local.x < -0.857 || local.x > 0.857)
       {
          // some 9th order approximation
          local.x3 = local.x * local.x * local.x
          local.x9 = local.x3 * local.x3 * local.x3
          
          local.out = local.x + (0.5 * level.PI - 1.0) * local.x9
       }
       else
       {
          local.x2 = local.x * local.x
          local.x3 = local.x2 * local.x
          local.x5 = local.x3 * local.x2
       
          // Taylor series expansion
          local.out = local.x + 0.1667 * local.x3 + 0.075 * local.x5
       }
    end local.out
    
    // inverse cos
    arccos local.rad:
       local.result = 0.5 * level.PI - (waitthread arcsin local.rad)
    end local.result 
    
    
    // square-root
    sqrt local.x:
    	// sqrt(2)
    	local.SQRT_2 = 1.4142135623730951
    
    	// known values, how convenient
    	if(local.x == 0.0)
    	{
    		local.result = 0.0
    	}
    	else if(local.x == 1.0)
    	{
    		local.result = 1.0
    	}
    	else if(local.x == 2.0)
    	{
    		local.result = local.SQRT_2
    	}
    	else if (local.x < 0.0)
    	{
    		// error
    		println "ERROR[math::sqrt]: sqrt(" local.x ") has no real solution"
    		local.result = 0.0
    	}
    	else
    	{
    		// reduce x to [1,2] domain
    		local.wx = local.x
    		local.steps = 0
    		local.dividesteps = 0
    		
    		// reduce below 2.0
    		while (local.wx > 2.0)
    		{
    			local.wx = 0.5 * local.wx
    			local.steps++
    		}
    		
    		// increase above 1.0
    		while(local.wx < 1.0)
    		{
    			local.wx = 2.0 * local.wx
    			local.dividesteps++
    		}
    		
    		// evaluate in [1,2] domain
    		if(local.wx == 1.0)
    		{
    			local.eval = 1.0
    		}
    		else if (local.wx == 2.0)
    		{
    			local.eval = local.SQRT_2
    		}
    		else
    		{
    			// approximation
    			local.EVALSLOPE = 0.4267766953
    			local.EVALMOD = 1.224744871 - 1.51 * local.EVALSLOPE
    			local.eval = local.EVALSLOPE * local.wx + local.EVALMOD
    		}
    		
    		// multiply back to original domain
    		for(local.i = 1; local.i <= local.steps; local.i++)
    		{
    			local.eval = local.eval * local.SQRT_2
    		}
    		
    		// divide back to original domain
    		for(local.i = 1; local.i <= local.dividesteps; local.i++)
    		{
    			local.eval = local.eval / local.SQRT_2
    		}
    	
    		// correct until required accuracy has been reached
    		local.MAXREFINEMENTSTEPS = 2;
    
    		for(local.i = 1; local.i <= local.MAXREFINEMENTSTEPS; local.i++)
    		{
    			local.fact = local.eval * local.eval / local.x
    			local.eval = local.eval / (waitthread sqrt1 local.fact)
    		}
    		
    		local.result = local.eval
    	}
    end local.result
    
    // fast square-root
    // only usuable near x=1
    // great for normalizing
    sqrt1 local.x:
    	// McLaurin expansion
    	local.result = 0.5 + 0.5 * local.x - 0.125 * (local.x - 1.0) * (local.x - 1.0)
    end local.result

  4. #4
    Banned
    Join Date
    May 2010
    Location
    fuck off?
    Posts
    1,145

    Default

    wonder if it would be faster though, imagine taking skylimit and replacing it with better physics functions

  5. #5
    Developer
    Join Date
    Jun 2010
    Location
    Hungary
    Posts
    291

    Default

    I tried the script, square root worked fine, but the angle functions didn't give the correct result at all.

  6. #6
    Banned
    Join Date
    May 2010
    Location
    fuck off?
    Posts
    1,145

    Default

    which one, vectors_toangles ?

  7. #7
    Developer
    Join Date
    Jun 2010
    Location
    Hungary
    Posts
    291

    Default

    The trigonometric functions. I've not tried the vectors_toangles yet. I've tried sin 30 for example, this is just 0.5 but the script has given -1.000 etc...

  8. #8
    Über Prodigy & Developer Razo[R]apiD's Avatar
    Join Date
    May 2010
    Location
    Poland, Lublin
    Posts
    3,257

    Default

    you have to use radians, not angles.

    Code:
    // cos(x), x in rad

  9. #9
    Developer
    Join Date
    Jun 2010
    Location
    Hungary
    Posts
    291

    Default

    hmm i will try.

  10. #10
    Developer
    Join Date
    Jun 2010
    Location
    Hungary
    Posts
    291

    Default

    It's not perfect even using radians, it gives 0.570 for sin 180 instead of 0. Someone try it, please, though i think I did it well.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •