问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

帮我解释下这段C++代码,做火焰和熔浆效果的,

发布网友 发布时间:2022-04-26 05:08

我来回答

1个回答

热心网友 时间:2022-06-21 00:27

class CFireRoutine //烟火程序
{
public:
CFireRoutine(); //构造函数
virtual ~CFireRoutine(); //虚态的析构函数

// Functs (public)

void InitFire(); //初始化
void ClrHotSpots(); //清除燃烧点
void InitPallette(); //初始化调色板
void SetHotSpots(); //设置燃烧点
void MakeLines(); //生成扫描线
//渲染(视频内存,宽度,高度)
void Render(DWORD* pVideoMemory,
int iwidth,
int iheight);

//均值(在点x,y处)(像素均值?)
unsigned char Average(int x, int y);

// props
int m_iFlameHeight; //火焰高度
int m_iWidth; //宽度
int m_iHeight;//高度(应该是作图区高度)
//火焰来源,即从点火处的y坐标
int m_iFireSource;//The y position for the lit spots
int m_iFireChance; //燃烧几率
int m_iAvgFlameWidth; //火焰平均宽度
int m_iAlpha; //α(深度)

COLORREF m_FireColors[4]; //火焰颜色

BYTE* m_pFireBits; //火焰数据
DWORD m_pPalletteBuffer[256]; //调色板
long* m_pYIndexes; //颜色索引
};
//熔浆:
class CPlasmaRoutine
{
public:
CPlasmaRoutine();//构造函数
virtual ~CPlasmaRoutine();//虚态析构函数

// Methods
void SetDefaultValues(VARIANT* pExtParms);//设置缺省参数值(外部变量)
void InitializePlasma(VARIANT* pExtParms);//初始化岩浆参数
void Create(int iWidth,int iHeight);//按视图生成岩浆
void Render(DWORD* pBits, //按照像素位,视图宽度,高度,扫描线渲染
int iwidth,
int iheight,
int iLineLength);
//设置颜色索引的RGB值
void SetRGB(int iIndex,int R,int G,int B);

void InitCostBLTable(); //初始化损耗平衡表?BL是不是balance的意思啊?不知道,反正不是对比度和亮度,还是色彩饱和度?好像都不是
void InitPallette(); //初始化调色板

void CalcPlasma(); //计算岩浆
//按照颜色开始,颜色结束,颜色步长创建渐变色,存到buffer里面
void CreateGradient(COLORREF clrStart,COLORREF clrEnd,long lSteps,COLORREF* pBuffer);

// Props

int m_iWidth;//视图宽度
int m_iHeight;//视图高度
int m_iAlpha;//视图深度

BYTE* m_pPlasmaBits; //岩浆序列缓冲
DWORD m_pPalletteBuffer[256];//调色板
int m_icostbl[256];//损耗平衡表
COLORREF m_PlasmaColors[16];// Yep 16 colors needed to generate our pallete... 采用16种颜色产生调色板
//以下应该是曲线拟合用的贝塞尔曲线四个控制点和矢量坐标
unsigned char m_a1,m_a2,m_a3,m_a4,m_b1,m_b2,m_b3,m_b4;

int m_iModifier1;
int m_iModifier2;
int m_iModifier3;
int m_iModifier4;
//双方向修改器(两点拉拽形成的矢量)
int m_iXModifier1;
int m_iXModifier2;
int m_iYModifier1;
int m_iYModifier2;

};

// FireRoutine.cpp: implementation of the CFireRoutine class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "FireRoutine.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction 构造函数,初始化所有参数,注意火源初始值为2,燃烧概率初始值为10
//////////////////////////////////////////////////////////////////////

CFireRoutine::CFireRoutine()
{
m_iWidth = 0;
m_iHeight = 0;
m_pFireBits = NULL;
m_pYIndexes = NULL;
m_iFireSource = 2;
m_iFireChance = 10;
m_iFlameHeight = 50;
m_iAlpha = 255;

m_FireColors[0] = RGB(0,0,0);// Black
m_FireColors[1] = RGB(255,0,0);// Red
m_FireColors[2] = RGB(255,255,0);// Yellow
m_FireColors[3] = RGB(255,255,255);// White
m_iAvgFlameWidth = 35;
}

//析构函数,如果颜色索引和渲染缓冲区存在则注销
CFireRoutine::~CFireRoutine()
{
if(m_pFireBits != NULL)
delete [] m_pFireBits;

if(m_pYIndexes != NULL)
delete [] m_pYIndexes;

m_pFireBits = NULL;
m_pYIndexes = NULL;
}
void CFireRoutine::InitFire()
{
// Get Rid of anything already there 初始化火焰,如果存在颜色索引和渲染缓冲则首先注销
if(m_pFireBits != NULL)
delete [] m_pFireBits;

if(m_pYIndexes != NULL)
delete [] m_pYIndexes;

// Add three to the height 高度自动加三
m_iHeight+=3;

m_pYIndexes = new long[m_iHeight]; //颜色索引时以火焰高度为长度的一个长整形数组

m_pFireBits = new BYTE[m_iWidth*m_iHeight]; //渲染缓冲区为一个W*H长度的字符型数组

// Clear the Fire bits 将火焰缓冲区置零
memset(m_pFireBits,0,(m_iWidth*m_iHeight));
// do all the y index pre-calc.. 在计算之前先将颜色缓冲值初始化为每个元素=宽度*高度
for (int y = m_iHeight; y >0; y--)
m_pYIndexes[y] = y * m_iWidth;

// Create our pallete

InitPallette(); //初始化调色板
ClrHotSpots(); //清除燃烧点

}
//所谓清除燃烧点就是将渲染缓冲区的某一行清零。哪一行呢?就是颜色索引中火源指向的那一行。
void CFireRoutine::ClrHotSpots()
{
// clear the fire line
memset(&m_pFireBits[m_pYIndexes[m_iFireSource]],0,m_iWidth);
}

//初始化调色板。您可能需要首先了解一下调色板的概念:虽然一个图可能是彩色的,但是每个像素如果
//都按照RGB三个字节方式存储,则成本太高了。调色板在于,假设这个图还是彩图,但是经过色彩分析,
//其中只有256种颜色是图中的常用颜色,这样一个字节就可以代表一个像素了,不过这个字节的值指的
//并不是RGB这种色彩矢量,而是256种颜色的代码,这256种颜色就是这幅图的调色板。
void CFireRoutine::InitPallette()
{
// Create a gradient between all the colors we have for our fire... 为我们的火焰创造一个过渡色使用的所有颜色

long iCount = 0;
COLORREF clrStart;
COLORREF clrEnd;

for(int iColor = 1;iColor<4;iColor++) //火焰的四个颜色定义
{

clrStart = m_FireColors[iColor-1]; //设置过渡色的起始颜色
clrEnd = m_FireColors[iColor]; //设置过渡色的终止颜色

int r, g, b; // First distance, then starting value 先计算距离,再计算值
float rStep, gStep, bStep; // Step size for each color //每种颜色的过渡步进值

// Get the color differences 取得三个颜色RGB的起始颜色和过渡颜色色差
r = (GetRValue(clrEnd) - GetRValue(clrStart));
g = (GetGValue(clrEnd) - GetGValue(clrStart));
b = (GetBValue(clrEnd) - GetBValue(clrStart));

int nSteps = max(abs(r), max(abs(g), abs(b))); //过渡步长数量取为RGB红绿蓝中色差最大者
float fStep = (float)(255/3)/ (float)nSteps; //将色差步长值转换为浮点数
// Calculate the step size for each color
rStep = r/(float)nSteps;//求得各颜色分量的色差步长值
gStep = g/(float)nSteps;
bStep = b/(float)nSteps;

// Reset the colors to the starting position 将颜色设置为渐进色初始颜色
r = GetRValue(clrStart);
g = GetGValue(clrStart);
b = GetBValue(clrStart);

for (int iOnBand = 0; iOnBand < nSteps; iOnBand++) //按照RGB计算出在渐变色全程中每个颜色的实际值
{
//COLORREF color = RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand);
COLORREF color = RGB(b + bStep *iOnBand, g + gStep*iOnBand,r+rStep*iOnBand);

long lIndex = (int)(iOnBand * fStep);

if(lIndex+((iColor-1)*85) < 255)
m_pPalletteBuffer[lIndex+((iColor-1)*85)] = color; //计算结果放到调色板里面去
}
}
// Step on the second color a little bit...向终止颜色过渡,以下颜色生成的内容与上面基本一致。
clrStart = m_FireColors[0];
clrEnd = m_FireColors[1];

for(int kj=0;kj<m_iFlameHeight;kj++)
m_pPalletteBuffer[kj] = 0;

int r, g, b; // First distance, then starting value
float rStep, gStep, bStep; // Step size for each color

// Get the color differences
r = (GetRValue(clrEnd) - GetRValue(clrStart));
g = (GetGValue(clrEnd) - GetGValue(clrStart));
b = (GetBValue(clrEnd) - GetBValue(clrStart));

int nSteps = max(abs(r), max(abs(g), abs(b)));
float fStep = (float)(85-m_iFlameHeight)/ (float)nSteps;
// Calculate the step size for each color
rStep = r/(float)nSteps;
gStep = g/(float)nSteps;
bStep = b/(float)nSteps;

// Reset the colors to the starting position
r = GetRValue(clrStart);
g = GetGValue(clrStart);
b = GetBValue(clrStart);

for (int iOnBand = 0; iOnBand < nSteps; iOnBand++)
{
//COLORREF color = RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand);
COLORREF color = RGB(b + bStep *iOnBand, g + gStep*iOnBand,r+rStep*iOnBand);

long lIndex = (int)(iOnBand * fStep);

m_pPalletteBuffer[lIndex+(85-m_iFlameHeight)] = color; //填写颜色值
}

}
// Macro to get a random integer within a specified range */ 这是一个按照范围取随机数的宏
#define getrandom( min, max ) (( rand() % (int)((( max ) + 1 ) - ( min ))) + ( min ))
#include <time.h>

void CFireRoutine::SetHotSpots() //设置燃烧点
{
ClrHotSpots(); //首先清除燃烧点
//m_iAvgFlameWidth

long lPosition = 0; //按照横轴位置进行累加,直到抵达宽度界限
while(lPosition < m_iWidth)
{
// see if we should do a flame
if (getrandom(0,100) < m_iFireChance) //得到一个随机数,看看是不是在燃烧概率范围内,如果不是就跳过去
{
// get a flame width
long lFlameWidth = getrandom(1,m_iAvgFlameWidth); //随机取得一个火焰宽度
for(int i=0;i<lFlameWidth;i++)
{
if(lPosition < m_iWidth) //如果位置在屏幕范围内,设置一个燃烧点
{
m_pFireBits[m_pYIndexes[m_iFireSource]+lPosition] =254;// set a hot spot!
lPosition++;
}
}
}
lPosition++;
}
// for (x = 0; x < m_iWidth; x++)
// {
// if (getrandom(0,100) < m_iFireChance)
// {

// }
// }
}

void CFireRoutine::MakeLines() //生成渲染扫描线
{
int x, y;

for (x = 0; x < m_iWidth; x++) //横向循环,从屏幕左侧到右侧
{
for (y = m_iFireSource; y<m_iHeight-1;y++) //纵向循环,从火源到火焰高度
// for (y = m_iHeight; y > m_iFireSource; y--)
{
//m_pFireBits[m_pYIndexes[y-1]+x] =Average(x,y);
m_pFireBits[m_pYIndexes[y+1]+x] =Average(x,y); //火焰值为扫描线均值
}
}
}
unsigned char CFireRoutine::Average(int x, int y)
{

unsigned char ave_color;
unsigned char ave1, ave2, ave3, ave4, ave5, ave6, ave7;

// Make sure we are not at the last line... 只要不是扫描线最后一样,平均值按照下列方式计算。
if(y == m_iHeight)
ave1 = m_pFireBits[m_pYIndexes[y-1] + x];
else
ave1 = m_pFireBits[m_pYIndexes[y + 1] + x];
//扫描线均值的方法,以x,y为中心,小半径为1,大半径为2的横向椭圆,从这个范围内取得颜色,然后求均值:
//基本上是下面这个图的样式:格式:取点编号(坐标)
/*
1#(x, y+1)
6#(x-2, y) 4#(x-1, y) 7#(x,y) 3#(x+1, y) 5#(x+2, y)
2#(x, y-1)
*/

ave2 = m_pFireBits[m_pYIndexes[y - 1] + x];
ave3 = m_pFireBits[m_pYIndexes[y] + x + 1];
ave4 = m_pFireBits[m_pYIndexes[y] + x - 1];
ave5 = m_pFireBits[m_pYIndexes[y] + x + 2];
ave6 = m_pFireBits[m_pYIndexes[y] + x - 2];
ave7 = m_pFireBits[m_pYIndexes[y] + x];

ave_color = (ave1 + ave2 + ave3 + ave4 + ave5 + ave6 + ave7) / 7;

//求出颜色均值并返回
return(ave_color);
}

//按照视频内存进行渲染
void CFireRoutine::Render(DWORD* pVideoMemory,
int iwidth,
int iheight
)
{
SetHotSpots(); // generate random hotspots 产生燃烧点
MakeLines(); // do all the math and screen updating //产生扫描线,更新屏幕

// Right now Im just going to blit it right onto the video memory //向视频内存做BitBlt缓冲拷贝
unsigned char* pSrcBitlin;// = m_pFireBits+(m_iWidth*3);// get rid of our fire source //获取火源
BYTE *dst;//=(BYTE*)Dib->pVideoMemory;

BYTE r;
BYTE g;
BYTE b;

for(int i=0;i<m_iHeight-3;i++) //逐行扫描
{
dst = (BYTE*)&pVideoMemory[(iwidth*i)]; //取得视频当前行
pSrcBitlin =&m_pFireBits[m_pYIndexes[i+3]]; //设置扫描线数据指针

for(int x=0;x<m_iWidth;x++)
{
//合成颜色,注意,是索引颜色取RGB分量后加上深度和饱和度,移位
r = GetRValue(m_pPalletteBuffer[pSrcBitlin[x]]);
g = GetGValue(m_pPalletteBuffer[pSrcBitlin[x]]);
b = GetBValue(m_pPalletteBuffer[pSrcBitlin[x]]);

dst[0]=(BYTE)(((r-dst[0])*m_iAlpha+(dst[0]<<8))>>8);
dst[1]=(BYTE)(((g-dst[1])*m_iAlpha+(dst[1]<<8))>>8);
dst[2]=(BYTE)(((b-dst[2])*m_iAlpha+(dst[2]<<8))>>8);
dst+=4;
}
}

}
关于岩浆和水波的源代码,概念差不多,都是首先建立颜色模型、然后匹配到缓冲中去,仔细对比一下就看懂了
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
八月中国最凉快的地方 八月份哪里最凉快,去哪旅游好?美丽的地方 乱字同韵字是什么意思 华硕笔记本电脑触摸板怎么开笔记本电脑触摸板怎么开启和关闭_百度知 ... 陕西职务侵占案立案准则 结婚后我的恋情维系了十年,怎么做到的? 玉米仁子饭产自哪里 中国期货交易所的交易品种有哪些? 历史要怎么读,有啥诀窍 高中历史诀窍 一道VB的程序题 求VB6 画二次函数图象的方法 目标检测中anchor box的做法和adaboost人脸检测中的滑窗检测有什么区别 vb 如何用For...Next...语句画sin图像? VB作图问题 p300 正常曲线图 谁能告诉我photoshop中拾色器的几个颜色模式的含义!!! 匡威的鞋子怎么样好吗 匡威的鞋子怎么看能详细的告诉我么 法国公司注册流程与优势? 匡威的来源,产地是哪里? 公司想要注册法国商标,法国注册商标的流程是怎么样的? 申请法国公司的流程 有匡威这个品牌的信息吗? 注册法国公司注册程序 Converse的鞋子的特点? 法国商标注册基本步骤都有哪些? converse 简介? 如何注册法国公司,中国人可以注册法国公司吗 什么叫匡威鞋 VB 在桌面屏幕上画一条直线如何让它重绘? 谁能帮我把c100m5y60k0这个颜色用RGB模式表示出来。谢谢 制作函数y=1/x图像的VB6.0程序代码 网络用语bkpp是什么意思 bkpp在哪个app直播 bkpp是指什么 月经走了六天然后第六天又出血了血是黑褐色的事怎么回事? bkpp是真恋人吗 月经干净第六天又来了,而且血是褐色的,怎么回事啊? 如何看待bkpp的关系 法院传票通过什么渠道送的 法院送文书是什么意思 法院送传票的是什么人 法院去家里送材料是送什么? 法院送传票如果用邮寄的方式有什么条件? 法院送传票一般还送什么?具体点 法院一般以什么方式送传票 法院送传票的费用该谁出 法院送传票收费吗 法院传票寄送到什么地方?