【发布时间】:2011-03-20 08:36:43
【问题描述】:
我目前正在尝试在 C++ 中创建光线追踪器,但我在编写最后生成的 .bmp 时遇到了困难。我决心手动完成,所以我可以了解更多关于图像文件和编写它们等的信息。但我遇到了一些困难。我对 C++ 很陌生,但使用 Python 已经有一段时间了。
我现在差不多了,我只有一个奇怪的问题。在重要的颜色(我设置为 0)中,一切都是正确的(我设置为 0),其中各种随机字符出现,并且在接下来的几个字节中继续,几个字节进入像素数据。在那之前和之后一切都很好,但我无法解释。我当前的代码正在编辑中:
这是十六进制:
问题区域突出显示
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
//-------------------------Object list
const int renderSize[2] = {254,254};
float sphere1Pos[3] = {0.0,0.0,0.0}; //first sphere at origin to make calculations easier
float sphere1Radius = 10.0;
float sphere1Colour= (255.0,0.0,0.0);
float light1Pos = (0.0,20.0,0.0); //Above sphere
float light1Intensity = 0.5;
// ------------------------
float dot(float* a,float* b); //Calculates the dot product
struct pixel {
unsigned char R;
unsigned char G;
unsigned char B;
};
//bmp--------------
struct bitmapMagicNumber {
unsigned char magicNumber[2];
};
struct bitmapFileHeader {
unsigned char fileSize;
short reserved1;
long reserved2;
short offset;
};
struct bitmapInformationHeader {
short headerSize;
short padding;
short width;
short height;
short planes;
short bitDepth;
short compression;
short imageSize;
short xPixelsPerMetre;
short yPixelsPerMetre;
short colours;
short importantColours;
};
void setBitmapMagicNumber(bitmapMagicNumber& magicNum){
magicNum.magicNumber[0] = 0x42;
magicNum.magicNumber[1] = 0x4D;
};
void setBitmapFileHeader(bitmapFileHeader& fileHeader,bitmapInformationHeader& informationHeader,pixel pixelArray) {
fileHeader.fileSize = 54 + sizeof(pixelArray);
fileHeader.reserved1 = 0;
fileHeader.reserved2 = 0;
fileHeader.offset = 54;
};
void setBitmapInformationHeader(bitmapInformationHeader& informationHeader){
informationHeader.headerSize = 40;
informationHeader.padding=0;
informationHeader.width = renderSize[0];
informationHeader.height = renderSize[1];
informationHeader.planes = 1;
informationHeader.bitDepth = 24;
informationHeader.compression = 0;
informationHeader.imageSize = 0;
informationHeader.xPixelsPerMetre = 0;
informationHeader.yPixelsPerMetre = 0 ;
informationHeader.colours = 0;
informationHeader.importantColours = 0;
};
void writeBitmap(bitmapMagicNumber& magicNum, bitmapFileHeader& fileHeader,bitmapInformationHeader& informationHeader,pixel pixelArray){
ofstream out("test.bmp",ios::out|ios::binary);
//file header
out.write((char*) &magicNum,2);
out.write((char*) &fileHeader.fileSize,sizeof(fileHeader.fileSize));
if (sizeof(fileHeader.fileSize)<3){
out.write((char*) &informationHeader.padding,1);
}
out.write((char*) &informationHeader.padding,1);
out.write((char*) &fileHeader.reserved1,2);
out.write((char*) &fileHeader.reserved2,2);
out.write((char*) &fileHeader.offset,sizeof(fileHeader.offset));
out.write((char*) &informationHeader.padding,1);
out.write((char*) &informationHeader.padding,1);
//information header
out.write((char*) &informationHeader.headerSize,sizeof(informationHeader.headerSize));
out.write((char*) &informationHeader.padding,1);
out.write((char*) &informationHeader.padding,1);
out.write((char*) &informationHeader.width,sizeof(informationHeader.width));
if (sizeof(informationHeader.width)<4){
out.write((char*) &informationHeader.padding,1);
}
if (sizeof(informationHeader.width)<3){
out.write((char*) &informationHeader.padding,1);
}
if (sizeof(informationHeader.width)<2){
out.write((char*) &informationHeader.padding,1);
}
out.write((char*) &informationHeader.height,sizeof(informationHeader.height));
if (sizeof(informationHeader.height)<4){
out.write((char*) &informationHeader.padding,1);
}
if (sizeof(informationHeader.height)<3){
out.write((char*) &informationHeader.padding,1);
}
if (sizeof(informationHeader.height)<2){
out.write((char*) &informationHeader.padding,1);
}
out.write((char*) &informationHeader.planes,sizeof(informationHeader.planes));
out.write((char*) &informationHeader.bitDepth,sizeof(informationHeader.bitDepth));
out.write((char*) &informationHeader.compression,4);
out.write((char*) &informationHeader.imageSize,4);
out.write((char*) &informationHeader.xPixelsPerMetre,4);
out.write((char*) &informationHeader.yPixelsPerMetre,4);
out.write((char*) &informationHeader.colours,4);
out.write((char*) &informationHeader.importantColours,4);
//pixel data
for (int y=0; y < renderSize[1]; y++) {
for (int x=0; x< renderSize[0]; x++) {
out.write((char*) &pixelArray[x][y],sizeof(pixel));
}
}
out.close();
}
// end bmp-----------
int main() {
pixel pixelArray[renderSize[0]][renderSize[1]];
for (int y=0; y < renderSize[1]; y++) {
for (int x=0; x< renderSize[0]; x++) {
float rayPos[3] = {x,y, -1000.0};
float rayDir[3] = {0.0,0.0,-1.0};
bool intersect;
//for each object in scene, see if intersects. (for now there is only one object to make things easier)
//-------sphere ray intersection....
float distance[3];
distance[0]= rayPos[0]-sphere1Pos[0];
distance[1]= rayPos[1]-sphere1Pos[1];
distance[2]= rayPos[2]-sphere1Pos[2];
float a = dot(rayDir, rayDir);
float b = 2 * dot(rayDir, distance);
float c = dot(distance, distance) - (sphere1Radius * sphere1Radius);
float disc = b * b - 4 * a * c;
if (disc < 0)
intersect=false;
else
intersect=true;
//--------------------
if (intersect==true){
pixelArray[x][y].R = 0;
pixelArray[x][y].G = 0;
pixelArray[x][y].B = 0;
}
else {
pixelArray[x][y].R = 0;
pixelArray[x][y].G = 0;
pixelArray[x][y].B = 0;
}
// trace to lights (as long as another object is not in the way)
}
}
//write .bmp
bitmapMagicNumber magicNum;
bitmapFileHeader fileHeader;
bitmapInformationHeader informationHeader;
setBitmapMagicNumber(magicNum);
setBitmapFileHeader(fileHeader,informationHeader, pixelArray[renderSize[0]][renderSize[1]]);
setBitmapInformationHeader(informationHeader);
writeBitmap(magicNum,fileHeader,informationHeader, pixelArray[renderSize[0]][renderSize[1]]);
}
//calculate dot product
float dot(float* a,float* b)
{
float dp = 0.0;
for (int i=0;i<3;i++)
dp += a[i] * b[i];
return dp;
}
【问题讨论】:
-
“我对 C++ 还很陌生,但使用 Python 已经有一段时间了。” C++ 与 Python 完全不同。如果您还没有一本好的 C++ 书籍,请考虑从The Definitive C++ Book Guide and List 获取一本介绍性 C++ 书籍。
-
我有一个并且已经阅读了,我只是觉得我的经验不足值得一提,因为这可能是我的一些错误的原因。
-
@Elephantic:太好了!我只是想确定一下。 :-) 很多人试图在没有一本好书的情况下学习,但结果通常并不好。
-
不要使用
<pre>或<code>- 选择代码并按010按钮或缩进至少 4 个空格。 -
啊,好的。我试图按下按钮然后粘贴代码。感谢您修复它:)