Ground spot texture drawing

dev-ui
Piotr Dziwinski 2012-10-20 16:34:22 +02:00
parent 6d06c9f722
commit 40e065aea9
3 changed files with 269 additions and 11 deletions

View File

@ -190,6 +190,15 @@ Math::IntPoint CImage::GetSize() const
return Math::IntPoint(m_data->surface->w, m_data->surface->h);
}
/** Image must be valid. */
void CImage::Fill(Gfx::IntColor color)
{
assert(m_data != nullptr);
Uint32 c = SDL_MapRGBA(m_data->surface->format, color.r, color.g, color.b, color.a);
SDL_FillRect(m_data->surface, nullptr, c);
}
/**
* Image must be valid and pixel coords in valid range.
*

View File

@ -79,6 +79,9 @@ public:
//! Returns the image size
Math::IntPoint GetSize() const;
//! Fills the whole image with given color
void Fill(Gfx::IntColor color);
//! Sets the color at given pixel
void SetPixel(Math::IntPoint pixel, Gfx::Color color);

View File

@ -1638,6 +1638,7 @@ void CEngine::CreateGroundMark(Math::Vector pos, float radius,
{
m_groundMark.LoadDefault();
m_groundMark.draw = true;
m_groundMark.phase = ENG_GR_MARK_PHASE_INC;
m_groundMark.delay[0] = delay1;
m_groundMark.delay[1] = delay2;
@ -3409,8 +3410,262 @@ void CEngine::DrawInterface()
void CEngine::UpdateGroundSpotTextures()
{
// TODO the original code modifying the textures is very complex, so stub for now
GetLogger()->Trace("CEngine::UpdateGroundSpotTextures(): stub!\n");
if (!m_firstGroundSpot &&
m_groundMark.drawPos.x == m_groundMark.pos.x &&
m_groundMark.drawPos.z == m_groundMark.pos.z &&
m_groundMark.drawRadius == m_groundMark.radius &&
m_groundMark.drawIntensity == m_groundMark.intensity) return;
for (int s = 0; s < 16; s++)
{
Math::Point min, max;
min.x = (s%4) * 254.0f - 1.0f; // 1 pixel cover
min.y = (s/4) * 254.0f - 1.0f;
max.x = min.x + 254.0f + 2.0f;
max.y = min.y + 254.0f + 2.0f;
bool clear = false;
bool set = false;
// Calculate the area to be erased.
int dot = static_cast<int>(m_groundMark.drawRadius/2.0f);
float tu, tv;
float cx, cy;
tu = (m_groundMark.drawPos.x+1600.0f)/3200.0f;
tv = (m_groundMark.drawPos.z+1600.0f)/3200.0f; // 0..1
cx = (tu*254.0f*4.0f)-0.5f;
cy = (tv*254.0f*4.0f)-0.5f;
if (dot == 0)
{
cx += 0.5f;
cy += 0.5f;
}
float px = cx-Math::Mod(cx, 1.0f);
float py = cy-Math::Mod(cy, 1.0f); // multiple of 1
if (m_firstGroundSpot ||
(m_groundMark.drawRadius != 0.0f &&
px+dot >= min.x && py+dot >= min.y &&
px-dot <= max.x && py-dot <= max.y))
{
clear = true;
}
// Calculate the area to draw.
dot = static_cast<int>(m_groundMark.radius/2.0f);
tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
cx = (tu*254.0f*4.0f)-0.5f;
cy = (tv*254.0f*4.0f)-0.5f;
if ( dot == 0 )
{
cx += 0.5f;
cy += 0.5f;
}
px = cx - Math::Mod(cx, 1.0f);
py = cy - Math::Mod(cy, 1.0f); // multiple of 1
if (m_groundMark.draw &&
px+dot >= min.x && py+dot >= min.y &&
px-dot <= max.x && py-dot <= max.y)
{
set = true;
}
if (clear || set)
{
CImage shadowImg(Math::IntPoint(256, 256));
shadowImg.Fill(Gfx::IntColor(255, 255, 255, 255));
// Draw the new shadows.
for (int i = 0; i < static_cast<int>( m_groundSpots.size() ); i++)
{
if ( m_groundSpots[i].used == false ||
m_groundSpots[i].radius == 0.0f ) continue;
if ( m_groundSpots[i].min == 0.0f &&
m_groundSpots[i].max == 0.0f )
{
dot = static_cast<int>(m_groundSpots[i].radius/2.0f);
tu = (m_groundSpots[i].pos.x+1600.0f)/3200.0f;
tv = (m_groundSpots[i].pos.z+1600.0f)/3200.0f; // 0..1
cx = (tu*254.0f*4.0f) - 0.5f;
cy = (tv*254.0f*4.0f) - 0.5f;
if (dot == 0)
{
cx += 0.5f;
cy += 0.5f;
}
px = cx-Math::Mod(cx, 1.0f);
py = cy-Math::Mod(cy, 1.0f); // multiple of 1
if ( px+dot < min.x || py+dot < min.y ||
px-dot > max.x || py-dot > max.y ) continue;
for (int iy = -dot; iy <= dot; iy++)
{
for (int ix =- dot; ix <= dot; ix++)
{
float ppx = px+ix;
float ppy = py+iy;
if ( ppx < min.x || ppy < min.y ||
ppx >= max.x || ppy >= max.y ) continue;
float intensity;
if (dot == 0)
intensity = 0.0f;
else
intensity = Math::Point(ppx-cx, ppy-cy).Length()/dot;
Gfx::Color color;
color.r = Math::Norm(m_groundSpots[i].color.r+intensity);
color.g = Math::Norm(m_groundSpots[i].color.g+intensity);
color.b = Math::Norm(m_groundSpots[i].color.b+intensity);
ppx -= min.x; // on the texture
ppy -= min.y;
shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
}
}
}
else
{
for (int iy = 0; iy < 256; iy++)
{
for (int ix = 0; ix < 256; ix++)
{
Math::Vector pos;
pos.x = (256.0f * (s%4) + ix) * 3200.0f/1024.0f - 1600.0f;
pos.z = (256.0f * (s/4) + iy) * 3200.0f/1024.0f - 1600.0f;
pos.y = 0.0f;
float level = m_terrain->GetFloorLevel(pos, true);
if ( level < m_groundSpots[i].min ||
level > m_groundSpots[i].max ) continue;
float intensity;
if (level > (m_groundSpots[i].max+m_groundSpots[i].min)/2.0f)
intensity = 1.0f - (m_groundSpots[i].max-level) / m_groundSpots[i].smooth;
else
intensity = 1.0f - (level-m_groundSpots[i].min) / m_groundSpots[i].smooth;
if (intensity < 0.0f) intensity = 0.0f;
Gfx::Color color;
color.r = Math::Norm(m_groundSpots[i].color.r+intensity);
color.g = Math::Norm(m_groundSpots[i].color.g+intensity);
color.b = Math::Norm(m_groundSpots[i].color.b+intensity);
shadowImg.SetPixel(Math::IntPoint(ix, iy), color);
}
}
}
}
if (set)
{
dot = static_cast<int>(m_groundMark.radius/2.0f);
tu = (m_groundMark.pos.x + 1600.0f) / 3200.0f;
tv = (m_groundMark.pos.z + 1600.0f) / 3200.0f; // 0..1
cx = (tu*254.0f*4.0f)-0.5f;
cy = (tv*254.0f*4.0f)-0.5f;
if (dot == 0)
{
cx += 0.5f;
cy += 0.5f;
}
px = cx-Math::Mod(cx, 1.0f);
py = cy-Math::Mod(cy, 1.0f); // multiple of 1
for (int iy = -dot; iy <= dot; iy++)
{
for (int ix = -dot; ix <= dot; ix++)
{
float ppx = px+ix;
float ppy = py+iy;
if (ppx < min.x || ppy < min.y ||
ppx >= max.x || ppy >= max.y) continue;
ppx -= min.x; // on the texture
ppy -= min.y;
float intensity = 1.0f - Math::Point(ix, iy).Length() / dot;
if (intensity <= 0.0f) continue;
intensity *= m_groundMark.intensity;
int j = (ix+dot) + (iy+dot) * m_groundMark.dx;
if (m_groundMark.table[j] == 1) // green ?
{
Gfx::Color color;
color.r = Math::Norm(1.0f-intensity);
color.g = 1.0f;
color.b = Math::Norm(1.0f-intensity);
shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
}
if (m_groundMark.table[j] == 2) // red ?
{
Gfx::Color color;
color.r = 1.0f;
color.g = Math::Norm(1.0f-intensity);
color.b = Math::Norm(1.0f-intensity);
shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
}
}
}
}
std::stringstream str;
str << "shadow" << std::setfill('0') << std::setw(2) << s << ".png";
std::string texName = str.str();
DeleteTexture(texName);
Gfx::Texture tex = m_device->CreateTexture(&shadowImg, m_defaultTexParams);
m_texNameMap[texName] = tex;
m_revTexNameMap[tex] = texName;
}
}
for (int i = 0; i < static_cast<int>( m_groundSpots.size() ); i++)
{
if (m_groundSpots[i].used == false ||
m_groundSpots[i].radius == 0.0f)
{
m_groundSpots[i].drawRadius = 0.0f;
}
else
{
m_groundSpots[i].drawPos = m_groundSpots[i].pos;
m_groundSpots[i].drawRadius = m_groundSpots[i].radius;
}
}
m_groundMark.drawPos = m_groundMark.pos;
m_groundMark.drawRadius = m_groundMark.radius;
m_groundMark.drawIntensity = m_groundMark.intensity;
m_firstGroundSpot = false;
}
void CEngine::DrawShadow()
@ -3607,7 +3862,6 @@ void CEngine::DrawShadow()
m_device->SetRenderState(RENDER_STATE_LIGHTING, true);
}
// STATUS: TESTED, VERIFIED
void CEngine::DrawBackground()
{
if (m_skyMode && m_cloud->GetLevel() != 0.0f) // clouds ?
@ -3627,7 +3881,6 @@ void CEngine::DrawBackground()
}
}
// STATUS: TESTED
void CEngine::DrawBackgroundGradient(const Color& up, const Color& down)
{
Math::Point p1(0.0f, 0.5f);
@ -3658,7 +3911,6 @@ void CEngine::DrawBackgroundGradient(const Color& up, const Color& down)
AddStatisticTriangle(2);
}
// Status: TESTED, VERIFIED
void CEngine::DrawBackgroundImage()
{
Math::Point p1, p2;
@ -3729,7 +3981,6 @@ void CEngine::DrawPlanet()
m_planet->Draw(); // draws the planets
}
// Status: PART_TESTED
void CEngine::DrawForegroundImage()
{
if (m_foregroundName.empty()) return;
@ -3765,10 +4016,8 @@ void CEngine::DrawForegroundImage()
AddStatisticTriangle(2);
}
// Status: PART_TESTED
void CEngine::DrawOverColor()
{
// TODO: fuzzy compare?
if ( (m_overColor == Color(0.0f, 0.0f, 0.0f, 0.0f) && m_overMode == ENG_RSTATE_TCOLOR_BLACK) ||
(m_overColor == Color(1.0f, 1.0f, 1.0f, 1.0f) && m_overMode == ENG_RSTATE_TCOLOR_WHITE) ) return;
@ -3805,7 +4054,6 @@ void CEngine::DrawOverColor()
AddStatisticTriangle(2);
}
// Status: TESTED, VERIFIED
void CEngine::DrawHighlight()
{
Math::Point min, max;
@ -3897,7 +4145,6 @@ void CEngine::DrawHighlight()
m_device->DrawPrimitive(PRIMITIVE_LINE_STRIP, line, 3);
}
// Status: TESTED, VERIFIED
void CEngine::DrawMouse()
{
MouseMode mode = m_app->GetMouseMode();
@ -3931,7 +4178,6 @@ void CEngine::DrawMouse()
DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon2);
}
// Status: TESTED, VERIFIED
void CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon)
{
if (icon == -1)