예제 #1
0
/** Given a matrix transform and a set of points returns an orthogonal projection matrix that maps coordinates of
    transformed points between -1 and 1.
*  \param transform a transform matrix.
*  \param pointsInside a vector of point in 3d space.
*/
core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std::vector<vector3df> &pointsInside)
{
    float xmin = std::numeric_limits<float>::infinity();
    float xmax = -std::numeric_limits<float>::infinity();
    float ymin = std::numeric_limits<float>::infinity();
    float ymax = -std::numeric_limits<float>::infinity();
    float zmin = std::numeric_limits<float>::infinity();
    float zmax = -std::numeric_limits<float>::infinity();

    for (unsigned i = 0; i < pointsInside.size(); i++)
    {
        vector3df TransformedVector;
        transform.transformVect(TransformedVector, pointsInside[i]);
        xmin = MIN2(xmin, TransformedVector.X);
        xmax = MAX2(xmax, TransformedVector.X);
        ymin = MIN2(ymin, TransformedVector.Y);
        ymax = MAX2(ymax, TransformedVector.Y);
        zmin = MIN2(zmin, TransformedVector.Z);
        zmax = MAX2(zmax, TransformedVector.Z);
    }

    float left = xmin;
    float right = xmax;
    float up = ymin;
    float down = ymax;

    core::matrix4 tmp_matrix;
    // Prevent Matrix without extend
    if (left == right || up == down)
        return tmp_matrix;
    tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
        down, up,
        30, zmax);
    return tmp_matrix;
}
예제 #2
0
void BuildCylinder(   
        core::array<video::S3DVertex>& vertexArray,
        core::array<u16>& indexArray,
        core::aabbox3d<f32>& boundingBox,
        
        f32 height,
        f32 startRadius,
        f32 endRadius,
        s32 radialSegments,
        
        const core::matrix4& transform,
        
        f32 startTCoordY = 0.0f,
        f32 endTCoordY = 1.0f,
        video::SColor startColor = video::SColor(255,255,255,255),
        video::SColor endColor = video::SColor(255,255,255,255) )
{
    u16 vertexIndex = vertexArray.size();
    
    s32 radialVertices = radialSegments + 1; // We want one additional vertex to make the texture wraps correctly
    
    // Place bottom cap
    for ( s32 i=0; i<radialVertices; i++ )
    {
        f32 angle = 2.0f * core::PI * i / (f32)( radialSegments );
        
        core::vector3df dir;
        dir.X = cos(angle);
        dir.Z = sin(angle);
        
        core::vector3df pos;
        core::vector3df normal = dir;

        pos = dir * startRadius;
        
        // Place bottom vertex
        transform.transformVect( pos );
        transform.rotateVect( normal );
        
        core::vector2df tcoord;
        tcoord.X = (f32)( i ) / (f32)( radialSegments );
        tcoord.Y = startTCoordY;
        
        vertexArray.push_back( video::S3DVertex(
            pos,
            normal,
            startColor,
            tcoord  ) );
        
        boundingBox.addInternalPoint( pos );
    }
    
    // Place top cap and indices
    for ( s32 i=0; i<radialVertices; i++ )
    {
        f32 angle = 2.0f * core::PI * i / (f32)( radialSegments );
        
        core::vector3df dir;
        dir.X = cos(angle);
        dir.Z = sin(angle);
        
        core::vector3df normal = dir;
        core::vector3df pos = dir * endRadius;
        pos.Y = height;
        
        transform.transformVect( pos ); 
        transform.rotateVect( normal );
        
        core::vector2df tcoord;
        tcoord.X = (f32)( i ) / (f32)( radialSegments );
        tcoord.Y = endTCoordY;
        
        vertexArray.push_back( video::S3DVertex(
            pos,
            normal,
            endColor,
            tcoord  ) );
        
        boundingBox.addInternalPoint(pos);
        
        // Add indices
        if ( i != radialVertices-1 )
        {
            s32 i2 = (i+1)%radialVertices;
            // Place the indices
            indexArray.push_back ( vertexIndex + i );
            indexArray.push_back ( vertexIndex + radialVertices + i );
            indexArray.push_back ( vertexIndex + i2 );
            
            indexArray.push_back ( vertexIndex + radialVertices + i );
            indexArray.push_back ( vertexIndex + radialVertices + i2 );
            indexArray.push_back ( vertexIndex + i2 );
        }
    }
}
예제 #3
0
// ----------------------------------------------------------------------------
void STKParticle::stimulateNormal(float dt, unsigned int active_count,
                                  std::vector<CPUParticle>* out)
{
    const core::matrix4 cur_matrix = AbsoluteTransformation;
    core::vector3df previous_frame_position, current_frame_position,
        previous_frame_direction, current_frame_direction;
    for (unsigned i = 0; i < m_max_count; i++)
    {
        core::vector3df new_particle_position;
        core::vector3df new_particle_direction;
        float new_size = 0.0f;
        float new_lifetime = 0.0f;

        const core::vector3df particle_position =
            m_particles_generating[i].m_position;
        const float lifetime = m_particles_generating[i].m_lifetime;
        const core::vector3df particle_direction =
            m_particles_generating[i].m_direction;
        const float size = m_particles_generating[i].m_size;

        const core::vector3df particle_position_initial =
            m_initial_particles[i].m_position;
        const float lifetime_initial = m_initial_particles[i].m_lifetime;
        const core::vector3df particle_direction_initial =
            m_initial_particles[i].m_direction;
        const float size_initial = m_initial_particles[i].m_size;

        float updated_lifetime = lifetime + (dt / lifetime_initial);
        if (updated_lifetime > 1.0f)
        {
            if (i < active_count)
            {
                float dt_from_last_frame =
                    glslFract(updated_lifetime) * lifetime_initial;
                float coeff = dt_from_last_frame / dt;

                m_previous_frame_matrix.transformVect(previous_frame_position,
                    particle_position_initial);
                cur_matrix.transformVect(current_frame_position,
                    particle_position_initial);

                core::vector3df updated_position = previous_frame_position
                    .getInterpolated(current_frame_position, coeff);

                m_previous_frame_matrix.rotateVect(previous_frame_direction,
                    particle_direction_initial);
                cur_matrix.rotateVect(current_frame_direction,
                    particle_direction_initial);

                core::vector3df updated_direction = previous_frame_direction
                    .getInterpolated(current_frame_direction, coeff);
                // + (current_frame_position - previous_frame_position) / dt;

                // To be accurate, emitter speed should be added.
                // But the simple formula
                // ( (current_frame_position - previous_frame_position) / dt )
                // with a constant speed between 2 frames creates visual
                // artifacts when the framerate is low, and a more accurate
                // formula would need more complex computations.

                new_particle_position = updated_position + dt_from_last_frame *
                    updated_direction;
                new_particle_direction = updated_direction;

                new_lifetime = glslFract(updated_lifetime);
                new_size = glslMix(size_initial,
                    size_initial * m_size_increase_factor,
                    glslFract(updated_lifetime));
            }
            else
            {
                new_lifetime = glslFract(updated_lifetime);
                new_size = 0.0f;
            }
        }
        else
        {
            new_particle_position = particle_position +
                particle_direction * dt;
            new_particle_direction = particle_direction;
            new_lifetime = updated_lifetime;
            new_size = (size == 0.0f) ? 0.0f :
                glslMix(size_initial, size_initial * m_size_increase_factor,
                updated_lifetime);
        }
        m_particles_generating[i].m_position = new_particle_position;
        m_particles_generating[i].m_lifetime = new_lifetime;
        m_particles_generating[i].m_direction = new_particle_direction;
        m_particles_generating[i].m_size = new_size;
        if (out != NULL)
        {
            if (m_flips || new_size != 0.0f)
            {
                if (new_size != 0.0f)
                {
                    Buffer->BoundingBox.addInternalPoint
                        (new_particle_position);
                }
                out->emplace_back(new_particle_position, m_color_from,
                    m_color_to, new_lifetime, new_size);
            }
        }
    }
}   // stimulateNormal
예제 #4
0
// ----------------------------------------------------------------------------
void STKParticle::stimulateHeightMap(float dt, unsigned int active_count,
                                     std::vector<CPUParticle>* out)
{
    assert(m_hm != NULL);
    const core::matrix4 cur_matrix = AbsoluteTransformation;
    for (unsigned i = 0; i < m_max_count; i++)
    {
        core::vector3df new_particle_position;
        core::vector3df new_particle_direction;
        float new_size = 0.0f;
        float new_lifetime = 0.0f;

        const core::vector3df particle_position =
            m_particles_generating[i].m_position;
        const float lifetime = m_particles_generating[i].m_lifetime;
        const core::vector3df particle_direction =
            m_particles_generating[i].m_direction;

        const core::vector3df particle_position_initial =
            m_initial_particles[i].m_position;
        const float lifetime_initial = m_initial_particles[i].m_lifetime;
        const core::vector3df particle_direction_initial =
            m_initial_particles[i].m_direction;
        const float size_initial = m_initial_particles[i].m_size;

        bool reset = false;
        const int px = core::clamp((int)(256.0f *
            (particle_position.X - m_hm->m_x) / m_hm->m_x_len), 0, 255);
        const int py = core::clamp((int)(256.0f *
            (particle_position.Z - m_hm->m_z) / m_hm->m_z_len), 0, 255);
        const float h = particle_position.Y - m_hm->m_array[px][py];
        reset = h < 0.0f;

        core::vector3df initial_position, initial_new_position;
        cur_matrix.transformVect(initial_position, particle_position_initial);
        cur_matrix.transformVect(initial_new_position,
            particle_position_initial + particle_direction_initial);

        core::vector3df adjusted_initial_direction =
            initial_new_position - initial_position;
        float adjusted_lifetime = lifetime + (dt / lifetime_initial);
        reset = reset || adjusted_lifetime > 1.0f;
        reset = reset || lifetime < 0.0f;

        new_particle_position = !reset ?
            (particle_position + particle_direction * dt) : initial_position;
        new_lifetime = !reset ? adjusted_lifetime : 0.0f;
        new_particle_direction = !reset ?
            particle_direction : adjusted_initial_direction;
        new_size = !reset ?
            glslMix(size_initial, size_initial * m_size_increase_factor,
            adjusted_lifetime) : 0.0f;

        m_particles_generating[i].m_position = new_particle_position;
        m_particles_generating[i].m_lifetime = new_lifetime;
        m_particles_generating[i].m_direction = new_particle_direction;
        m_particles_generating[i].m_size = new_size;
        if (out != NULL)
        {
            if (m_flips || new_size != 0.0f)
            {
                if (new_size != 0.0f)
                {
                    Buffer->BoundingBox.addInternalPoint
                        (new_particle_position);
                }
                out->emplace_back(new_particle_position, m_color_from,
                    m_color_to, new_lifetime, new_size);
            }
        }
    }
}   // stimulateHeightMap