LineFlower3DSP
一个3D屏保程序,算法的原理类似于圆内轮旋线的生成.
下载地址:
http://files.cnblogs.com/WhyEngine/LineFlower3D_sp.zip
切图:
双击"LineFlower3DSP.scr"可运行程序
屏保设置方式
XP:
将目录下的所有文件拷贝到WINDOWS系统目录下如"C:\WINDOWS\system32"
在设置屏保的对话框中,选择"LineFlowerSP"
WIN7,WIN8
将目录下的所有文件拷贝到"C:\WINDOWS\SysWOW64"或"C:\WINDOWS\SysWOW32"目录下
在设置屏保的对话框中,选择"LineFlowerSP"
程序启动后,点击鼠标或按下键盘任意按键会自动退出
使用鼠标滚轮滚动进行切换
代码也贴出来.其实这代码写得麻烦了,如果对数学了解得深一些的话,可以使用更简单的算法生成.
/**************************************************************** File name : LineFlower.h
Author :
Version : 1.0a
Create Date : 2014/06/09
Description : *****************************************************************/ // -------------------------------------------------------------------------------------- #ifndef _LineFlower_H_
#define _LineFlower_H_ // -------------------------------------------------------------------------------------- #define MAX_CIRCLES_COUNT 200 struct LfVertex
{
float x;
float y;
float z;
}; // -------------------------------------------------------------------------------------- class CLineFlower
{
public:
CLineFlower(); void Reset(); void AutoSize(float width, float height); const LfVertex& GetVertex(unsigned int index)
{
return m_listVertices[index % m_nVerticesNum];
} public:
float m_listSinValues[];
float m_listCosValues[]; float m_fOutCircleRadius;
float m_fInCircleRadius;
float m_fScreenCircleRadius;
float m_fOffset;
float m_fStepScale0;
float m_fStepScale180;
float m_fOffsetScale0;
float m_fOffsetScale180; unsigned int m_zParam; float m_fHalfExtendXY;
float m_fHalfExtendZ;
float m_fHalfExtendXYZ; LfVertex m_listVertices[MAX_CIRCLES_COUNT * + ]; unsigned int m_nVerticesNum;
unsigned int m_nCirclesCount; bool m_enableZ;
}; // -------------------------------------------------------------------------------------- #endif
/**************************************************************** File name : LineFlower.cpp
Author :
Version : 1.0a
Create Date : 2014/06/09
Description : *****************************************************************/ // -------------------------------------------------------------------------------------- #include "LineFlower.h"
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h> // -------------------------------------------------------------------------------------- #define DEGREE_MAX_ERROR 3.0f // -------------------------------------------------------------------------------------- inline int yf_rand(int a)
{
return (int)(::rand() % a);
} inline int yf_rand(int a, int b)
{
return a + (int)(::rand() % (b-a));
} inline float yf_rand_real(float a)
{
return a * (float)(::rand() / ((float)RAND_MAX + ));
} inline float yf_rand_real(float a, float b)
{
const float r = (float)(::rand() / ((float)RAND_MAX + ));
return r*(b-a) + a;
} inline bool yf_rand_bool()
{
return (::rand() % == );
} inline float yf_lerp(float a, float b, float r)
{
return a + (b - a) * r;
} // -------------------------------------------------------------------------------------- CLineFlower::CLineFlower()
{
const float d2r = 0.01745329251994f;
float r;
for (unsigned int i = ; i < ; i++)
{
r = i * d2r;
m_listSinValues[i] = sinf(r);
m_listCosValues[i] = cosf(r);
} m_nVerticesNum = ;
m_nCirclesCount = ; memset(m_listVertices, , sizeof(m_listVertices)); m_enableZ = true;
} void CLineFlower::Reset()
{
m_fOutCircleRadius = yf_rand_real(8.0f, 64.0f);
m_fInCircleRadius = yf_rand_real(4.0f, 64.0f);
m_fOffset = yf_rand_real(2.0f, m_fInCircleRadius);
if (yf_rand_bool())
{
m_fOffset = -m_fOffset;
} m_fStepScale0 = yf_rand_real(0.1f, 1.0f);
if (yf_rand_bool())
{
m_fStepScale0 = 1.0f / m_fStepScale0;
}
m_fStepScale180 = yf_rand_real(0.1f, 1.0f);
if (yf_rand_bool())
{
m_fStepScale180 = 1.0f / m_fStepScale180;
} m_fOffsetScale0 = yf_rand_real(0.1f, 1.0f);
if (yf_rand_bool())
{
m_fOffsetScale0 = 1.0f / m_fOffsetScale0;
}
m_fOffsetScale180 = yf_rand_real(0.1f, 1.0f);
if (yf_rand_bool())
{
m_fOffsetScale180 = 1.0f / m_fOffsetScale180;
} m_fScreenCircleRadius = m_fOutCircleRadius + m_fInCircleRadius;
float step = m_fScreenCircleRadius / m_fInCircleRadius;
if (step > 360.0f)
{
return;
} float maxOffset = (m_fOffsetScale180 > m_fOffsetScale0) ? m_fOffsetScale180 : m_fOffsetScale0;
maxOffset *= fabs(m_fOffset);
m_fHalfExtendXY = m_fOutCircleRadius + maxOffset;
if (m_enableZ)
{
m_fHalfExtendZ = yf_rand_real(0.0f, 64.0f);
m_fHalfExtendXYZ = sqrtf(m_fHalfExtendXY*m_fHalfExtendXY + m_fHalfExtendZ*m_fHalfExtendZ);
}
else
{
m_fHalfExtendZ = 0.0f;
m_fHalfExtendXYZ = m_fHalfExtendXY;
} m_zParam = yf_rand(, ); m_nCirclesCount = MAX_CIRCLES_COUNT;
m_nVerticesNum = m_nCirclesCount * ; LfVertex vCenter;
float degree = ; LfVertex vPos0;
LfVertex vPos1;
unsigned int index;
float r, a;
float scale; for (unsigned int i = ; i < m_nCirclesCount; i++)
{
for (unsigned int j = ; j < ; j++)
{
vCenter.x = m_fOutCircleRadius*m_listSinValues[j];
vCenter.y = m_fOutCircleRadius*m_listCosValues[j];
if (m_enableZ)
{
vCenter.z = m_fHalfExtendZ*m_listSinValues[j*m_zParam % ];
}
else
{
vCenter.z = 0.0f;
} r = fabsf(degree - 180.0f) / 180.0f;
scale = yf_lerp(m_fOffsetScale0, m_fOffsetScale180, r); index = (unsigned int)degree;
vPos0.x = vCenter.x - m_fOffset*scale*m_listSinValues[index];
vPos0.y = vCenter.y - m_fOffset*scale*m_listCosValues[index]; vPos1.x = vCenter.x - m_fOffset*scale*m_listSinValues[index + ];
vPos1.y = vCenter.y - m_fOffset*scale*m_listCosValues[index + ]; a = degree - index;
LfVertex& v = m_listVertices[i* + j];
v.x = vPos0.x*(1.0f - a) + vPos1.x*a;
v.y = vPos0.y*(1.0f - a) + vPos1.y*a;
if (m_enableZ)
{
float dis = sqrtf(v.x*v.x + v.y*v.y);
v.z = vCenter.z * (1.0f - dis / m_fScreenCircleRadius);
}
else
{
v.z = 0.0f;
} scale = yf_lerp(m_fStepScale0, m_fStepScale180, r);
degree += step*scale;
degree = fmodf(degree, 360.0f);
} if (degree < DEGREE_MAX_ERROR || degree > 360.0f - DEGREE_MAX_ERROR)
{
m_nCirclesCount = i + ;
m_nVerticesNum = m_nCirclesCount * ;
m_listVertices[m_nVerticesNum] = m_listVertices[];
m_nVerticesNum++;
break;
}
}
} void CLineFlower::AutoSize(float width, float height)
{
float fMinX = FLT_MAX;
float fMaxX = -FLT_MAX;
float fMinY = FLT_MAX;
float fMaxY = -FLT_MAX; for (unsigned int i = ; i < m_nVerticesNum; i++)
{
if (fMinX > m_listVertices[i].x)
{
fMinX = m_listVertices[i].x;
}
if (fMaxX < m_listVertices[i].x)
{
fMaxX = m_listVertices[i].x;
} if (fMinY > m_listVertices[i].y)
{
fMinY = m_listVertices[i].y;
}
if (fMaxY < m_listVertices[i].y)
{
fMaxY = m_listVertices[i].y;
}
} float ox = fMaxX - fMinX;
float oy = fMaxY - fMinY; float halfWidth = width*0.5f;
float halfHeight = height*0.5f; for (unsigned int i = ; i < m_nVerticesNum; i++)
{
m_listVertices[i].x = -halfWidth + (m_listVertices[i].x - fMinX)*width/ox;
m_listVertices[i].y = -halfHeight + (m_listVertices[i].y - fMinY)*height/ox;
}
}