//rorger, 2011
//mishi.cpp
//密室光线反射
//last modified:2011-05-05 23:24
#include "myglbase.h"
#include "glut.h"
#include "windows.h"
#include "math.h"
#include "mymath.h"
#include "vector"
using namespace std;
//线段类
class Line2Segment
{
public:
Point2 first ;
Point2 second ;
Vector2 norm()
{
Vector2 c = second - first ;
Vector2 normalVector = c.GetNormalVector();
return normalVector;
}
Line2Segment()
{
first.x=first.y=0;
second.x=second.y=0;
}
Line2Segment(Point2 first,Point2 second)
{
this->first = first;
this->second = second;
}
Line2Segment(Line2Segment& line2)
{
first = line2.first;
second = line2.second;
}
};
//点法向量表示的直线类
class Line2
{
public:
Point2 pt ;
Vector2 norm;
Line2()
{
pt.x=pt.y=0;
norm.x=0;
norm.y=0;
}
Line2(Point2 pt,Vector2 norm)
{
this->pt=pt;
this->norm=norm;
}
Line2(const Line2& line2)
{
pt=line2.pt;
norm = line2.norm;
}
};
//点法向量表示的多边形
class Line2List
{
public:
vector<Line2> line;
int num()
{
return line.size();
}
void push_back(Line2 newLine)
{
line.push_back(newLine);
}
Line2& operator[](int index)
{
if ((unsigned int)index >= line.size()) //注意size是unsigned int
{
throw "Out of range in Line2List";
}
return line[index];
}
};
class PolygonList
{
public:
vector<Line2List> polygons;
int num()
{
return polygons.size();
}
void push_back(Line2List newPolygon)
{
polygons.push_back(newPolygon);
}
Line2List& operator[](int index)
{
if ((unsigned int)index >= polygons.size()) //注意size是unsigned int
{
throw "Out of range in Line2List";
}
return polygons[index];
}
};
/*
a: Vector2 -射入向量
n: Vector2 -直线法向量
r: Vector2 -a经过直线反射后的向量
*/
int GetReflectVector(Vector2 a,Vector2 n, Vector2& r)
{
if(n.GetLength() != 0)
{
n.Normalized(); //对n进行归一化,以便于利用公式
r=a-2*(a*n)*n; //公式请参考计算机图像学,这里a不要求归一化
return 1;
}
else
return 0 ;
}
int chopCIRadial(float&tIn,float&tOut,float number,float denom,Vector2 norm,Vector2& normInHit,Vector2& normOutHit)
{
float tHit ;
if(denom < 0) //射线是射入
{
tHit = number / denom ;
if (tOut != -1.0)
{
if (tHit >tOut)
{
return 0 ;
}
}
if(tHit>=tIn)
{
tIn = tHit;
normInHit = norm;
}
}
else if(denom > 0) //射线射出
{
tHit = number / denom;
if (tHit<tIn)
{
return 0 ;
}
if (tOut==-1.0) //这是第一次初始化使用的
{
tOut = tHit;
normOutHit = norm;
}
else if (tHit<tOut) //最早出去的
{
tOut = tHit;
normOutHit = norm;
}
}
else if(number<=0) //denom为0,射线与直线平行
{
return 0 ; //在外半空间
}
return 1;
}
/*
S: Point2 - 射线端点
c: Vector - 射线方向
L: Line2List&- 多边形截取区域
tIn: float& - 截取的射入时间
tOut: float& -截取的射出时间
normIn: Vector2& - 射入时击中的边的法向量
normOut: Vector2& - 射出时击中的边的法向量
*/
int CyrusBeckClipRadial(Point2 S,Vector2 c,Line2List& L,float& tIn,float& tOut,Point2& pIn,Point2& pOut,Vector2& normIn,Vector2& normOut)
{
float number,denom;
float tInTemp = 0.0,tOutTemp=-1.0;
Point2 pInTemp,pOutTemp ;
Vector2 normInTemp,normOutTemp ;
Vector2 tmp ;
for (int i=0;i<L.num();i++)
{
//利用公式 tHit=n*(B-A)/(n*c) 其中A和c是目的直线参数表示,B和n是另一条直线点法向量
tmp = L.line[i].pt - S;
number = L.line[i].norm * tmp ;
denom = L.line[i].norm * c ;
if (!chopCIRadial(tInTemp,tOutTemp,number,denom,L.line[i].norm,normInTemp,normOutTemp))
{
return 0 ; //提前结束
}
if (tInTemp>0.0 )
{
if(tIn==0.0)
{
tIn = tInTemp;
normIn = normInTemp;
}
else
{
tIn=max(tIn,tInTemp);
if (tIn == tInTemp)
{
normIn = normInTemp;
}
}
}
if (tOutTemp>=0.0)
{
if (tOut==-1.0)
{
tOut = tOutTemp;
normOut = normOutTemp ;
}
else
{
tOut = min(tOut,tOutTemp); //最早出去的
if (tOut == tOutTemp)
{
normOut = normOutTemp;
}
}
}
}
pIn = S+c*tIn;
pOut = S+c*tOut;
return 1;
}
/*
S: Point2 - 射线入射端点
c: Vector2 - 射线方向向量
polygonList: PolygonList& - 多边形集
pOut: Point2& - 取得最早的击中点
norm: Vector2& -取得最早击中点时边的法向量
*/
int CyrusBeckClipRadial(Point2 S,Vector2 c,PolygonList& polygonList,Point2& pOut ,Vector2& norm)
{
float tIn=0.0,tOut=-1.0,tInResult=0.0,tOutResult=-1.0,tHit=0.0;
Point2 pInTemp,pInResult,pOutTemp,pOutResult ;
Vector2 normInTemp,normOutTemp;
for (int i=0;i<polygonList.num();i++)
{
tIn=0.0;
tOut=-1.0;
//取得每个多边形的射入时间和射出时间,取最小值
if(!CyrusBeckClipRadial(S,c,polygonList[i],tIn,tOut,pInTemp,pOutTemp,normInTemp,normOutTemp))
{
continue;
}
else //如果射入时间大于0,那么必然是内柱的情况;
//如果射出时间大于0,那么必然是墙壁的情况;
//还有一种小角度的情况(我只考虑了墙壁)
{
if (tIn >0.0 && !IsEqual(tIn,0.0))
{
if (tHit == 0.0) // 首次
{
tHit = tIn;
norm = normInTemp;
}
else
{
tHit = min(tHit,tIn); //取得最小的射入时间
if (tHit == tIn)
{
norm = normInTemp;
}
}
}
else if (tOut >0.0 && !IsEqual(tOut,0.0))
{
if (tHit == 0.0) // 首次
{
tHit=tOut;
norm = normOutTemp;
}
else
{
tHit = min(tOut,tHit); //取得最小的射出时间
if (tHit == tOut)
{
norm = normOutTemp;
}
}
}
else //小角度反射时的处理情况
{
if (tOut>0.0 && tHit==0.0)
{
tHit = tOut;
norm = normOutTemp;
}
}
}
}
pOut = S+c*tHit;
return 1 ;
}
//测试下吧
void testReflects()
{
//这是外墙,点是顺时针表示
float outerPillar[6][2]=
{
{1,0.5},{0.3,5},{2.5,8},
{6,9},{8,4},{7,1}
};
//这是内柱,点是顺时针表示
float innerPillar[5][2]=
{
{1.8,5.5},{2.5,6.5},{3.5,7},
{4,4.5},{3,4.5}
};
//这是内柱,点是顺时针表示
float innerPillar2[3][2]=
{
{4.55,2.2},{5,5},{6.5,3.5}
};
//这是内柱,点是顺时针表示
float innerPillar3[5][2]=
{
{1.8,2.5},{2.5,3.5},{3.5,4},
{4,1.5},{3,1.5}
};
Line2List outerPolygon,innerPolygon,innerPolygon2,innerPolygon3;
Line2 tempLine2 ;
Point2 tempPoint ;
Point2 tempPoint2;
Vector2 tempNorm;
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINE_LOOP);
for (int i=0;i<6;i++)
{
tempPoint.x = outerPillar[i][0];
tempPoint.y = outerPillar[i][1];
tempPoint2.x = outerPillar[(i+1)%6][0];
tempPoint2.y = outerPillar[(i+1)%6][1];
tempLine2.norm = ((Vector2)(tempPoint2-tempPoint)).GetNormalVector();
tempLine2.pt = tempPoint;
outerPolygon.push_back(tempLine2);
glVertex2d(tempPoint.x,tempPoint.y);
}
glEnd();
glBegin(GL_LINE_LOOP);
for (int i=0;i<5;i++)
{
tempPoint.x = innerPillar[i][0];
tempPoint.y = innerPillar[i][1];
tempPoint2.x = innerPillar[(i+1)%5][0];
tempPoint2.y = innerPillar[(i+1)%5][1];
tempLine2.norm = ((Vector2)(tempPoint2-tempPoint)).GetNormalVector();
tempLine2.pt = tempPoint;
innerPolygon.push_back(tempLine2);
glVertex2d(tempPoint.x,tempPoint.y);
}
glEnd();
glBegin(GL_LINE_LOOP);
for (int i=0;i<3;i++)
{
tempPoint.x = innerPillar2[i][0];
tempPoint.y = innerPillar2[i][1];
tempPoint2.x = innerPillar2[(i+1)%3][0];
tempPoint2.y = innerPillar2[(i+1)%3][1];
tempLine2.norm = ((Vector2)(tempPoint2-tempPoint)).GetNormalVector();
tempLine2.pt = tempPoint;
innerPolygon2.push_back(tempLine2);
glVertex2d(tempPoint.x,tempPoint.y);
}
glEnd();
glBegin(GL_LINE_LOOP);
for (int i=0;i<5;i++)
{
tempPoint.x = innerPillar3[i][0];
tempPoint.y = innerPillar3[i][1];
tempPoint2.x = innerPillar3[(i+1)%5][0];
tempPoint2.y = innerPillar3[(i+1)%5][1];
tempLine2.norm
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
mishi.rar (11个子文件)
mishi
LineReflects
LineReflects.vcproj 4KB
CyrusBeckRadial.cpp 7KB
myglbase.cpp 6KB
myglbase.h 2KB
mymath.h 127B
mishi2.cpp 10KB
LineReflects.cpp 8KB
mymath.cpp 173B
LineReflects.vcproj.Rorger-PC.Rorger.user 1KB
mishi.sln 902B
mishi.suo 22KB
共 11 条
- 1
资源评论
- wocanoname2012-09-30一般,很简单的例子,如果你想做比较麻烦的光反射的模型,这个就算了。
- Faiz-lsp2013-08-08要7分有点多不过还是谢谢,简单参考下
- mazhen12014-05-07没运行成功,不过还是谢谢了,很有参考价值
rorger
- 粉丝: 62
- 资源: 18
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功