体绘制RayCasting(光线投影算法)C++OpenGL源码

体绘制RayCasting(光线投影算法)C++OpenGL源码RayCasting(光线投影算法)C++源码
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <GL/glut.h>
#define EPSILON 0.000001
#define WIDTH 400
#define HEIGTH 500
float Image[WIDTH*HEIGTH*4];
void GenerateVolume(int *Data,int* Dim);//⽣成体数据
void GenCube(int x,int y,int z,int side,int density, int *Data,int *Dim);//⽣成正⽅体数据
void GenSphere(int x,int y,int z,int radius,int density,int *Data,int *Dim);//⽣成球体数据
void Classify(float* CData,int *Data,int *Dim);//数据分类上海冷气机厂
void RotationMatrix(float *R,float *eye,float *center,float *up);//求取图像空间到物体空间变换的旋转矩阵
void Composite(float *rgba,int x0,int y0,float *CData,int *Dim,float *R,float *T);//合成像素颜⾊值
bool Intersection(float *startpos, float *pos, float *dir,int *Dim);//求光线与包围盒交点坐标
void TrInterpolation(float *rgba,float *pos,float *CData,int *Dim);//三线性插值
bool CheckinBox(float *point,int *Dim);//判断点是否在包围盒内
void MatrixmulVec(float *c,float *a,float *b);//矩阵向量乘积
void CrossProd(float *c,float *a,float *b);//向量叉乘
void Normalize(float *norm,float *a);//向量归⼀化
void Mydisplay();//显⽰图像
int main(int argc,char **argv)
{
东方影都2003int Dim[3]={200,200,200};//体数据⼤⼩
int *Data=(int *)malloc(sizeof(int)*Dim[0]*Dim[1]*Dim[2]);
float *CData=(float*)malloc(sizeof(float)*Dim[0]*Dim[1]*Dim[2]*4);
float R[9];//旋转矩阵
float T[3]={0,0,450};//平移向量(要根据R调整,以保证获得体数据全貌)
float eye[3]={0.5,0.5,1};//视点位置
float center[3]={0,0,0};//物体参考点位置
float up[3]={0,1,0};//相机朝上的⽅向
RotationMatrix(R,eye,center,up);//获得旋转矩阵
GenerateVolume(Data,Dim);//⽣成原始体数据
Classify(CData,Data,Dim);//对体数据分类
float *LinePS=Image;
for(int j=0;j<HEIGTH;j++)//逐个合成像素值
{
for(int i=0;i<WIDTH;i++)
{
Composite(LinePS,i,j,CData,Dim,R,T);
LinePS+=4;
}
}
free(Data);
free(CData);
//使⽤OpenGL显⽰此⼆维图像
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowSize(500,500);
glutInitWindowPosition(200,200);
glutCreateWindow("Ray-Casting");
glClearColor (1,1,1,1);//背景设为⽩⾊
门的悬念glutDisplayFunc(Mydisplay);//显⽰图像
glutMainLoop();
}
//⽣成体数据
//********************************************************************//
//⽣成⼀个⼤正⽅体,内部包含⼀个球体,球体中间⼜包含⼀个⼩正⽅体//Data:体积数据
//Dim:体数据⼤⼩
//********************************************************************//
void GenerateVolume(int *Data,int *Dim)
{
GenCube(0,0,0,200,100,Data,Dim);//⼤正⽅体
GenSphere(100,100,100,80,200,Data,Dim);//球体
GenCube(70,70,70,60,300,Data,Dim);//⼩正⽅体
}
//⽣成正⽅体数据
//********************************************************************//
//x,y,z:正⽅体左下⾓坐标
//side:正⽅体边长
//density:正⽅体对应的标量值
//Data:体积数据
//Dim:体数据⼤⼩
//********************************************************************//
void GenCube(int x,int y,int z,int side,int density, int *Data,int *Dim)
{
int max_x=x+side,max_y=y+side,max_z=z+side;
int Dimxy=Dim[0]*Dim[1];
for(int k=z;k<max_z;k++)
{
for(int j=y;j<max_y;j++)
{
for(int i=x;i<max_x;i++)
{
Data[k*Dimxy+j*Dim[0]+i]=density;
}
}
}
}
//⽣成球体数据
//********************************************************************//
//x,y,z:球⼼坐标
//radius:球半径
//density:球体对应的标量值
//Data:体积数据
//Dim:体数据⼤⼩
嗳呵婴儿特润护肤霜//********************************************************************//
void GenSphere(int x,int y,int z,int radius,int density,int *Data,int *Dim) {
int radius2=radius*radius;
int Dimxy=Dim[0]*Dim[1];
for(int k=0;k<Dim[2];k++)模糊数学模型
{
for(int j=0;j<Dim[1];j++)
{
for(int i=0;i<Dim[0];i++)
{
if((i-x)*(i-x)+(j-y)*(j-y)+(k-z)*(k-z)<=radius2)
{
Data[k*Dimxy+j*Dim[0]+i]=density;
ca126
}
}
}
}
}
//数据分类
//********************************************************************//
//将原始体数据的标量值映射为颜⾊和不透明度
//这⾥处理的⽐较简单,直接将之前⽣成的数据分三类:⼤正⽅体⽩⾊、球体红⾊、⼩正⽅体黄⾊//CData:分类后体数据
//Data:原始体数据
//Dim:体数据⼤⼩
//********************************************************************//
void Classify(float* CData,int *Data,int *Dim)
{
int *LinePS=Data;
float *LinePD=CData;
for(int k=0;k<Dim[2];k++)
{
for(int j=0;j<Dim[1];j++)
{
for(int i=0;i<Dim[0];i++)
{
if(LinePS[0]<=100)
{
//⽩⾊
LinePD[0]=1.0;
LinePD[1]=1.0;
LinePD[2]=1.0;
LinePD[3]=0.005;
}
else if(LinePS[0]<=200)
{
//红⾊
LinePD[0]=1.0;
LinePD[1]=0.0;
LinePD[2]=0.0;
LinePD[3]=0.015;
}
else
{
//黄⾊
LinePD[0]=1.0;
LinePD[1]=1.0;
LinePD[2]=0.0;
LinePD[3]=0.02;
}
LinePS++;
LinePD+=4;
}
}
}
}
//求取从图像空间到物体空间变换的旋转矩阵
//********************************************************************//
//功能类似于OpenGL中的gluLookAt函数
/
/参考:blog.csdn/popy007/article/details/5120158
//R:旋转矩阵
//eye:视点位置
//center:物体参考点位置
//up:相机朝上的⽅向
//********************************************************************//
void RotationMatrix(float *R,float *eye,float *center,float *up)
{
float XX[3],YY[3],ZZ[3];//图像空间的基向量
ZZ[0]=eye[0]-center[0];
ZZ[1]=eye[1]-center[1];
ZZ[2]=eye[2]-center[2];
CrossProd(XX,up,ZZ);
CrossProd(YY,ZZ,XX);
Normalize(XX,XX);
Normalize(YY,YY);
Normalize(ZZ,ZZ);
//由图像空间基向量构成旋转矩阵
R[0]=XX[0];R[1]=YY[0];R[2]=ZZ[0];
R[3]=XX[1];R[4]=YY[1];R[5]=ZZ[1];
R[6]=XX[2];R[7]=YY[2];R[8]=ZZ[2];
}
/
/合成像素值
//********************************************************************//
//rgba:合成颜⾊值
//x0,y0:⼆维图像像素坐标
//CData:分类后体数据
//Dim:体数据⼤⼩
//R:旋转矩阵(换⽤于图像空间到物体空间的转换)
//T:平移向量(同上)
//********************************************************************//
void Composite(float *rgba,int x0,int y0,float *CData,int *Dim,float *R,float *T)
{
int stepsize=1;//采样步长
float cumcolor[4];//累计颜⾊值
cumcolor[0]=cumcolor[1]=cumcolor[2]=cumcolor[3]=0.0;
float pos[3],dir[3];//投射光线起点、⽅向
float startpos[3];//光线与包围盒近视点处的交点坐标
float samplepos[3];//采样点坐标
float samplecolor[4];//采样点颜⾊
//采⽤平⾏投影,故在图像空间中投射光线的⽅向(0,0,-1),起点(x0,y0,0)
pos[0]=x0;pos[1]=y0;pos[2]=0;
//将光线描述转换到物体空间
//*********************************//
dir[0]=-R[2];dir[1]=-R[5];dir[2]=-R[8];//光线⽅向在物体空间的表达
MatrixmulVec(pos,R,pos);//旋转
pos[0]+=T[0];//平移
pos[1]+=T[1];
pos[2]+=T[2];
//*********************************//
if(Intersection(startpos,pos,dir,Dim))//判断光线与包围盒是否相交
{
samplepos[0]=startpos[0];
samplepos[1]=startpos[1];
samplepos[2]=startpos[2];
while(CheckinBox(samplepos,Dim)&&cumcolor[3]<1)//当光线射出包围盒或累计不透明度超过1时中⽌合成  {
TrInterpolation(samplecolor,samplepos,CData,Dim);//三线性插值获得采样点处的颜⾊及不透明度
//合成颜⾊及不透明度,采⽤的是从前到后的合成公式
cumcolor[0] +=samplecolor[0]*samplecolor[3]*(1-cumcolor[3]);//R
cumcolor[1] +=samplecolor[1]*samplecolor[3]*(1-cumcolor[3]);//G
cumcolor[2] +=samplecolor[2]*samplecolor[3]*(1-cumcolor[3]);//B
cumcolor[3] +=samplecolor[3]*(1-cumcolor[3]);    //A
//下⼀个采样点
samplepos[0]+=dir[0]*stepsize;
samplepos[1]+=dir[1]*stepsize;
samplepos[2]+=dir[2]*stepsize;
}
rgba[0]=cumcolor[0];
rgba[1]=cumcolor[1];
rgba[2]=cumcolor[2];
rgba[3]=cumcolor[3];
return;
}
rgba[0]=rgba[1]=rgba[2]=rgba[3]=1.0;//若光线与包围盒不相交,赋⽩⾊
}
//判断投射光线与包围盒是否相交(若相交,求靠近视点处的交点坐标)
//********************************************************************//
/
/思路:将包围盒6个⾯⽆限扩展,并分成3组,即平⾏于XOY,YOZ,ZOX平⾯的各有2个;//求光线与6个平⾯的交点,从每组的2个交点中选出距离视点较近者,这样得到3个候
//选交点;从这3个候选交点中选出距离视点最远的那个。最后判断这个点是否落在包
//围盒内,若在,即为光线与包围盒的靠近视点处的交点。
//stratpos:靠近视点处的交点坐标
//pos:光线起点坐标
//dir:光线⽅向向量
//Dim:包围盒右上⾓坐标(左下⾓坐标为(0,0,0))
//********************************************************************//
bool Intersection(float *startpos, float *pos, float *dir,int *Dim)
{
float nearscale = -1000000;
float scale1, scale2;
//光线与包围盒平⾏于YOZ的2个平⾯交点
if ((dir[0] <=-EPSILON)||(dir[0] >=EPSILON))
{
scale1 = (0- pos[0]) / dir[0];
scale2 = (Dim[0] -1 - pos[0]) / dir[0];
//选出靠近视点的交点,并与当前候选点⽐较,保留较远者
if (scale1 < scale2)
{
if (scale1 > nearscale)
nearscale = scale1;
}
else
{
if (scale2 > nearscale)
nearscale = scale2;
}
}
//光线与包围盒平⾏于ZOX的2个平⾯交点
if ((dir[1] <=-EPSILON)||(dir[1] >=EPSILON))
{
scale1 = (0 - pos[1]) / dir[1];
scale2 = (Dim[1] -1 - pos[1]) / dir[1];
//选出靠近视点的交点,并与当前候选点⽐较,保留较远者
if (scale1 < scale2)
{
if (scale1 > nearscale)
nearscale = scale1;
}
else
{
if (scale2 > nearscale)
nearscale = scale2;
}
}
//光线与包围盒平⾏于XOY的2个平⾯交点
if ((dir[2] <=-EPSILON)||(dir[2] >=EPSILON))
{
scale1 = (0 - pos[2]) / dir[2];
scale2 = (Dim[2] -1 - pos[2]) / dir[2];
//选出靠近视点的交点,并与当前候选点⽐较,保留较远者
if (scale1 < scale2)
{
if (scale1 > nearscale)
nearscale = scale1;
}
else
{
if (scale2 > nearscale)
nearscale = scale2;
}
}
startpos[0] = pos[0] + nearscale * dir[0] ;

本文发布于:2024-09-21 01:32:02,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/212473.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:JBox2D详解
标签:空间   光线   数据
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议