LineFlower3DSP
一个3D屏保程序,算法的原理类似于圆内轮旋线的生成.
下载地址:
http://files.cnblogs.com/WhyEngine/LineFlower3D_sp.zip
切图:
双击"LineFlower3DSP.scr"可运行程序
屏保设置方式
XP:
将目录下的所有文件拷贝到WINDOWS系统目录下如"C:WINDOWSsystem32"
在设置屏保的对话框中,选择"LineFlowerSP"
WIN7,WIN8
将目录下的所有文件拷贝到"C:WINDOWSSysWOW64"或"C:WINDOWSSysWOW32"目录下
在设置屏保的对话框中,选择"LineFlowerSP"
程序启动后,点击鼠标或按下键盘任意按键会自动退出
使用鼠标滚轮滚动进行切换
代码也贴出来.其实这代码写得麻烦了,如果对数学了解得深一些的话,可以使用更简单的算法生成.
1 /**************************************************************** 2 3 File name : LineFlower.h 4 Author : 5 Version : 1.0a 6 Create Date : 2014/06/09 7 Description : 8 9 *****************************************************************/ 10 11 // -------------------------------------------------------------------------------------- 12 13 #ifndef _LineFlower_H_ 14 #define _LineFlower_H_ 15 16 // -------------------------------------------------------------------------------------- 17 18 #define MAX_CIRCLES_COUNT 200 19 20 struct LfVertex 21 { 22 float x; 23 float y; 24 float z; 25 }; 26 27 // -------------------------------------------------------------------------------------- 28 29 class CLineFlower 30 { 31 public: 32 CLineFlower(); 33 34 void Reset(); 35 36 void AutoSize(float width, float height); 37 38 const LfVertex& GetVertex(unsigned int index) 39 { 40 return m_listVertices[index % m_nVerticesNum]; 41 } 42 43 public: 44 float m_listSinValues[361]; 45 float m_listCosValues[361]; 46 47 float m_fOutCircleRadius; 48 float m_fInCircleRadius; 49 float m_fScreenCircleRadius; 50 float m_fOffset; 51 float m_fStepScale0; 52 float m_fStepScale180; 53 float m_fOffsetScale0; 54 float m_fOffsetScale180; 55 56 unsigned int m_zParam; 57 58 float m_fHalfExtendXY; 59 float m_fHalfExtendZ; 60 float m_fHalfExtendXYZ; 61 62 LfVertex m_listVertices[MAX_CIRCLES_COUNT * 360 + 1]; 63 64 unsigned int m_nVerticesNum; 65 unsigned int m_nCirclesCount; 66 67 bool m_enableZ; 68 }; 69 70 // -------------------------------------------------------------------------------------- 71 72 #endif
1 /**************************************************************** 2 3 File name : LineFlower.cpp 4 Author : 5 Version : 1.0a 6 Create Date : 2014/06/09 7 Description : 8 9 *****************************************************************/ 10 11 // -------------------------------------------------------------------------------------- 12 13 #include "LineFlower.h" 14 #include <float.h> 15 #include <math.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 // -------------------------------------------------------------------------------------- 20 21 #define DEGREE_MAX_ERROR 3.0f 22 23 // -------------------------------------------------------------------------------------- 24 25 inline int yf_rand(int a) 26 { 27 return (int)(::rand() % a); 28 } 29 30 inline int yf_rand(int a, int b) 31 { 32 return a + (int)(::rand() % (b-a)); 33 } 34 35 inline float yf_rand_real(float a) 36 { 37 return a * (float)(::rand() / ((float)RAND_MAX + 1)); 38 } 39 40 inline float yf_rand_real(float a, float b) 41 { 42 const float r = (float)(::rand() / ((float)RAND_MAX + 1)); 43 return r*(b-a) + a; 44 } 45 46 inline bool yf_rand_bool() 47 { 48 return (::rand() % 2 == 1); 49 } 50 51 inline float yf_lerp(float a, float b, float r) 52 { 53 return a + (b - a) * r; 54 } 55 56 // -------------------------------------------------------------------------------------- 57 58 CLineFlower::CLineFlower() 59 { 60 const float d2r = 0.01745329251994f; 61 float r; 62 for (unsigned int i = 0; i < 361; i++) 63 { 64 r = i * d2r; 65 m_listSinValues[i] = sinf(r); 66 m_listCosValues[i] = cosf(r); 67 } 68 69 m_nVerticesNum = 0; 70 m_nCirclesCount = 0; 71 72 memset(m_listVertices, 0, sizeof(m_listVertices)); 73 74 m_enableZ = true; 75 } 76 77 void CLineFlower::Reset() 78 { 79 m_fOutCircleRadius = yf_rand_real(8.0f, 64.0f); 80 m_fInCircleRadius = yf_rand_real(4.0f, 64.0f); 81 m_fOffset = yf_rand_real(2.0f, m_fInCircleRadius); 82 if (yf_rand_bool()) 83 { 84 m_fOffset = -m_fOffset; 85 } 86 87 m_fStepScale0 = yf_rand_real(0.1f, 1.0f); 88 if (yf_rand_bool()) 89 { 90 m_fStepScale0 = 1.0f / m_fStepScale0; 91 } 92 m_fStepScale180 = yf_rand_real(0.1f, 1.0f); 93 if (yf_rand_bool()) 94 { 95 m_fStepScale180 = 1.0f / m_fStepScale180; 96 } 97 98 m_fOffsetScale0 = yf_rand_real(0.1f, 1.0f); 99 if (yf_rand_bool()) 100 { 101 m_fOffsetScale0 = 1.0f / m_fOffsetScale0; 102 } 103 m_fOffsetScale180 = yf_rand_real(0.1f, 1.0f); 104 if (yf_rand_bool()) 105 { 106 m_fOffsetScale180 = 1.0f / m_fOffsetScale180; 107 } 108 109 m_fScreenCircleRadius = m_fOutCircleRadius + m_fInCircleRadius; 110 float step = m_fScreenCircleRadius / m_fInCircleRadius; 111 if (step > 360.0f) 112 { 113 return; 114 } 115 116 float maxOffset = (m_fOffsetScale180 > m_fOffsetScale0) ? m_fOffsetScale180 : m_fOffsetScale0; 117 maxOffset *= fabs(m_fOffset); 118 m_fHalfExtendXY = m_fOutCircleRadius + maxOffset; 119 if (m_enableZ) 120 { 121 m_fHalfExtendZ = yf_rand_real(0.0f, 64.0f); 122 m_fHalfExtendXYZ = sqrtf(m_fHalfExtendXY*m_fHalfExtendXY + m_fHalfExtendZ*m_fHalfExtendZ); 123 } 124 else 125 { 126 m_fHalfExtendZ = 0.0f; 127 m_fHalfExtendXYZ = m_fHalfExtendXY; 128 } 129 130 m_zParam = yf_rand(1, 12); 131 132 m_nCirclesCount = MAX_CIRCLES_COUNT; 133 m_nVerticesNum = m_nCirclesCount * 360; 134 135 LfVertex vCenter; 136 float degree = 0; 137 138 LfVertex vPos0; 139 LfVertex vPos1; 140 unsigned int index; 141 float r, a; 142 float scale; 143 144 for (unsigned int i = 0; i < m_nCirclesCount; i++) 145 { 146 for (unsigned int j = 0; j < 360; j++) 147 { 148 vCenter.x = m_fOutCircleRadius*m_listSinValues[j]; 149 vCenter.y = m_fOutCircleRadius*m_listCosValues[j]; 150 if (m_enableZ) 151 { 152 vCenter.z = m_fHalfExtendZ*m_listSinValues[j*m_zParam % 360]; 153 } 154 else 155 { 156 vCenter.z = 0.0f; 157 } 158 159 r = fabsf(degree - 180.0f) / 180.0f; 160 scale = yf_lerp(m_fOffsetScale0, m_fOffsetScale180, r); 161 162 index = (unsigned int)degree; 163 vPos0.x = vCenter.x - m_fOffset*scale*m_listSinValues[index]; 164 vPos0.y = vCenter.y - m_fOffset*scale*m_listCosValues[index]; 165 166 vPos1.x = vCenter.x - m_fOffset*scale*m_listSinValues[index + 1]; 167 vPos1.y = vCenter.y - m_fOffset*scale*m_listCosValues[index + 1]; 168 169 a = degree - index; 170 LfVertex& v = m_listVertices[i*360 + j]; 171 v.x = vPos0.x*(1.0f - a) + vPos1.x*a; 172 v.y = vPos0.y*(1.0f - a) + vPos1.y*a; 173 if (m_enableZ) 174 { 175 float dis = sqrtf(v.x*v.x + v.y*v.y); 176 v.z = vCenter.z * (1.0f - dis / m_fScreenCircleRadius); 177 } 178 else 179 { 180 v.z = 0.0f; 181 } 182 183 scale = yf_lerp(m_fStepScale0, m_fStepScale180, r); 184 degree += step*scale; 185 degree = fmodf(degree, 360.0f); 186 } 187 188 if (degree < DEGREE_MAX_ERROR || degree > 360.0f - DEGREE_MAX_ERROR) 189 { 190 m_nCirclesCount = i + 1; 191 m_nVerticesNum = m_nCirclesCount * 360; 192 m_listVertices[m_nVerticesNum] = m_listVertices[0]; 193 m_nVerticesNum++; 194 break; 195 } 196 } 197 } 198 199 void CLineFlower::AutoSize(float width, float height) 200 { 201 float fMinX = FLT_MAX; 202 float fMaxX = -FLT_MAX; 203 float fMinY = FLT_MAX; 204 float fMaxY = -FLT_MAX; 205 206 for (unsigned int i = 0; i < m_nVerticesNum; i++) 207 { 208 if (fMinX > m_listVertices[i].x) 209 { 210 fMinX = m_listVertices[i].x; 211 } 212 if (fMaxX < m_listVertices[i].x) 213 { 214 fMaxX = m_listVertices[i].x; 215 } 216 217 if (fMinY > m_listVertices[i].y) 218 { 219 fMinY = m_listVertices[i].y; 220 } 221 if (fMaxY < m_listVertices[i].y) 222 { 223 fMaxY = m_listVertices[i].y; 224 } 225 } 226 227 float ox = fMaxX - fMinX; 228 float oy = fMaxY - fMinY; 229 230 float halfWidth = width*0.5f; 231 float halfHeight = height*0.5f; 232 233 for (unsigned int i = 0; i < m_nVerticesNum; i++) 234 { 235 m_listVertices[i].x = -halfWidth + (m_listVertices[i].x - fMinX)*width/ox; 236 m_listVertices[i].y = -halfHeight + (m_listVertices[i].y - fMinY)*height/ox; 237 } 238 }