예제 #1
0
inline void
ParametricSurface::GenerateVertices(vector<float>& vertices,
                                    unsigned char flags) const
{
    int floatsPerVertex = 3;
    if (flags & VertexFlagsNormals)
        floatsPerVertex += 3;
    if (flags & VertexFlagsTexCoords)
        floatsPerVertex += 2;

    vertices.resize(GetVertexCount() * floatsPerVertex);
    float* attribute = &vertices[0];

    for (int j = 0; j < m_divisions.y; j++) {
        for (int i = 0; i < m_divisions.x; i++) {

            // Compute Position
            vec2 domain = ComputeDomain(i, j);
            vec3 range = Evaluate(domain);
            attribute = range.Write(attribute);

            // Compute Normal
            if (flags & VertexFlagsNormals) {
                float s = i, t = j;

                // Nudge the point if the normal is indeterminate.
                if (i == 0) s += 0.01f;
                if (i == m_divisions.x - 1) s -= 0.01f;
                if (j == 0) t += 0.01f;
                if (j == m_divisions.y - 1) t -= 0.01f;
                
                // Compute the tangents and their cross product.
                vec3 p = Evaluate(ComputeDomain(s, t));
                vec3 u = Evaluate(ComputeDomain(s + 0.01f, t)) - p;
                vec3 v = Evaluate(ComputeDomain(s, t + 0.01f)) - p;
                vec3 normal = u.Cross(v).Normalized();
                if (InvertNormal(domain))
                    normal = -normal;
                attribute = normal.Write(attribute);
            }
            
            // Compute Texture Coordinates
            if (flags & VertexFlagsTexCoords) {
                float s = m_textureCount.x * i / m_slices.x;
                float t = m_textureCount.y * j / m_slices.y;
                attribute = vec2(s, t).Write(attribute);
            }
        }
    }
}
예제 #2
0
void MinimizeN<Real>::GetMinimum (const Real* t0, const Real* t1,
    const Real* tInitial, Real* tMin, Real& fMin)
{
    // For 1D function callback.
    mMinimizer.SetUserData(this);

    // The initial guess.
    size_t numBytes = mDimensions*sizeof(Real);
    mFCurr = mFunction(tInitial, mUserData);
    memcpy(mTSave, tInitial, numBytes);
    memcpy(mTCurr, tInitial, numBytes);

    // Initialize the direction set to the standard Euclidean basis.
    size_t numBasisBytes = numBytes*(mDimensions + 1);
    memset(mDirectionStorage, 0, numBasisBytes);
    int i;
    for (i = 0; i < mDimensions; ++i)
    {
        mDirection[i][i] = (Real)1;
    }

    Real ell0, ell1, ellMin;
    for (int iter = 0; iter < mMaxIterations; iter++)
    {
        // Find minimum in each direction and update current location.
        for (i = 0; i < mDimensions; ++i)
        {
            mDCurr = mDirection[i];
            ComputeDomain(t0, t1, ell0, ell1);
            mMinimizer.GetMinimum(ell0, ell1, (Real)0, ellMin, mFCurr);
            for (int j = 0; j < mDimensions; ++j)
            {
                mTCurr[j] += ellMin*mDCurr[j];
            }
        }

        // Estimate a unit-length conjugate direction.
        Real length = (Real)0;
        for (i = 0; i < mDimensions; ++i)
        {
            mDConj[i] = mTCurr[i] - mTSave[i];
            length += mDConj[i]*mDConj[i];
        }

        const Real epsilon = (Real)1e-06;
        length = Math<Real>::Sqrt(length);
        if (length < epsilon)
        {
            // New position did not change significantly from old one.
            // Should there be a better convergence criterion here?
            break;
        }

        Real invlength = ((Real)1)/length;
        for (i = 0; i < mDimensions; ++i)
        {
            mDConj[i] *= invlength;
        }

        // Minimize in conjugate direction.
        mDCurr = mDConj;
        ComputeDomain(t0, t1, ell0, ell1);
        mMinimizer.GetMinimum(ell0, ell1, (Real)0, ellMin, mFCurr);
        for (i = 0; i < mDimensions; ++i)
        {
            mTCurr[i] += ellMin*mDCurr[i];
        }

        // Cycle the directions and add conjugate direction to set.
        mDConj = mDirection[0];
        for (i = 0; i < mDimensions; ++i)
        {
            mDirection[i] = mDirection[i+1];
        }

        // Set parameters for next pass.
        memcpy(mTSave, mTCurr, numBytes);
    }

    memcpy(tMin, mTCurr, numBytes);
    fMin = mFCurr;
}