Search code examples
xsltmonoscientific-notation

Math results in scientific float and cannot calculate with it anymore


I am trying to make an xslt that can convert a position (vector3) via a quaternion to a new position. I have made the following set-up, but I am retrieving NaN's for very small values close to 0. How can I calculate further with the values that come from the quaternion to right-vector calculations?

<xsl:template name="object_markingtape_position">
  <xsl:param name="sign"/> <!-- left or right (-1 or 1) -->
  <xsl:param name="quaternion"/> <!-- quaternion in x,y,z,w -->
  <xsl:variable name="rightvec">
    <xsl:call-template name="QuatToRight">
      <xsl:with-param name="x" select="$quaternion/ns:x"/>
      <xsl:with-param name="y" select="$quaternion/ns:y"/>
      <xsl:with-param name="z" select="$quaternion/ns:z"/>
      <xsl:with-param name="w" select="$quaternion/ns:w"/>
    </xsl:call-template>
  </xsl:variable>

  Right vector y: <xsl:value-of select="number($rightvec/y)"/> <!-- results in a value with 1.5435434E-04 -->
  <xsl:element name="position" namespace="{$ns}">
    <xsl:element name="x" namespace="{$ns}">
      <xsl:value-of select="$sign * 1.5 * $rightvec/x + ns:position/ns:x"/>
    </xsl:element>
    <xsl:element name="y" namespace="{$ns}"> <!-- results into NaN -->
      <xsl:value-of select="$sign * 1.5 * $rightvec/y + ns:position/ns:y"/>
    </xsl:element>
    <xsl:element name="z" namespace="{$ns}">
      <xsl:value-of select="$sign * 1.5 * $rightvec/z + ns:position/ns:z"/>
    </xsl:element>
  </xsl:element>
</xsl:template>

<!-- Functionality for calculating the vectors from a quaternion -->
<!-- From http://nic-gamedev.blogspot.nl/2011/11/quaternion-math-getting-local-axis.html -->
<xsl:template name="QuatToRight">
  <xsl:param name="x"/>
  <xsl:param name="y"/>
  <xsl:param name="z"/>
  <xsl:param name="w"/>
  <xsl:element name="vec3">
    <xsl:element name="x">
      <xsl:value-of select="1 - 2 * ($x * $y - $w * $z)"/>
    </xsl:element>
    <xsl:element name="y">
      <xsl:value-of select="2 * ($x * $y + $w * $z)"/> 
    </xsl:element>
    <xsl:element name="z">
      <xsl:value-of select="2 * ($x * $z - $w * $y)"/>
    </xsl:element>
  </xsl:element>
</xsl:template>

An example of xml values that can come in are the following:

<Item>
  <position>
    <x>-106.6172</x>
    <y>0.780673563</y>
    <z>-13.0446815</z>
  </position>
  <rotation> <!-- this is where the quaternion param is filled with -->
    <x>0.0810996</x>
    <y>0.354339659</y>
    <z>-0.207844481</z>
    <w>-0.908111751</w>
  </rotation>
</Item>

Solution

  • I resolved this with some data loss, but it is the cleanest solution so far. I used format-number().

    <xsl:template name="QuatToRight">
      <xsl:param name="x"/>
      <xsl:param name="y"/>
      <xsl:param name="z"/>
      <xsl:param name="w"/>
      <xsl:element name="vec3">
        <xsl:element name="x">
          <xsl:value-of select="format-number(1 - 2 * ($x * $y - $w * $z),'0.000000')"/>
        </xsl:element>
        <xsl:element name="y">
          <xsl:value-of select="format-number(2 * ($x * $y + $w * $z),'0.000000')"/> 
        </xsl:element>
        <xsl:element name="z">
          <xsl:value-of select="format-number(2 * ($x * $z - $w * $y),'0.000000')"/>
        </xsl:element>
      </xsl:element>
    </xsl:template>