OSG世界坐标转屏幕坐标(转载)
#define M(row,col) m[col * 4 + row]
void Transform_Point(double out[4], const double m[16], const double in[4]){
out[0] = M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
out[1] = M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
out[2] = M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
out[3] = M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
}
osg::Vec3d WorldToScreen(osgViewer::View* view,osg::Vec3 worldpoint){
double in[4], out[4];
in[0] = worldpoint._v[0];
in[1] = worldpoint._v[1];
in[2] = worldpoint._v[2];
in[3] = 1.0;
//获得当前的投影矩阵和模型视图矩阵
osg::Matrix projectMatrix= view->getCamera()->getProjectionMatrix();
osg::Matrix viewprojectMatrix = view->getCamera()->getViewMatrix();
//下面计算 模型视图矩阵 * 投影矩阵 * 视口窗口变换矩阵
double modelViewMatrix[16];
memcpy(modelViewMatrix,viewprojectMatrix.ptr(),sizeof(GLdouble) * 16);
Transform_Point(out, modelViewMatrix, in);
double myprojectMatrix[16];
memcpy(myprojectMatrix,projectMatrix.ptr(),sizeof(GLdouble) * 16);
Transform_Point(in, myprojectMatrix, out);
if(int(in[3] * 100000) == 0){
return osg::Vec3d(0,0,0);
}
in[0] /= in[3];
in[1] /= in[3];
in[2] /= in[3];
int viewPort[4];
osg::Viewport* myviewPort = view->getCamera()->getViewport();
viewPort[0] = 0;
viewPort[1] = 0;
viewPort[2] = mConfigure->GetScreenWidthPixel(); //横向象素点
viewPort[3] = mConfigure->GetScreenHeightPixel();//纵向象素点
//计算 三维点在屏幕上的二维投影点
osg::Vec3d sceenPoint;
sceenPoint._v[0] = (int)(viewPort[0] + (1 + in[0]) * viewPort[2] / 2 + 0.5);
sceenPoint._v[1] = (int)(viewPort[1] + (1 + in[1]) * viewPort[3] / 2 + 0.5);
sceenPoint._v[2] = 0;
return sceenPoint;
}
我目前只是尝试使用了MatrixTransform PositionAttitudeTransform Group Projection Switch 等各种功能的组节点. 在介绍MatrixTransform 和 PositionAttitudeTransform 节点前.我想先介绍下osg当中矩阵的一些相关知识.
其实,无需关心osg矩阵是如何实现的.但是要记住的是osg中采用的左乘操作,我们平时里讨论的操作如旋转平移等.
OpenGL的: newpos = R* T * oldpos //先执行平移 后执行 旋转 (全局坐标系)
osg当中: newpos =oldpos * T *R //先执行平移 后执行旋转 (全局坐标系)
因为在osg当中矩阵执行的操作则是行矩阵操作.因此为了跟OpenGL的列矩阵做同步 而不在定义的时候就相当于做了一个转置操作.即

因此在osg/State 中 在使用applyModelViewMatrix() osg/State 是OpenGL状态机的封装.是与OpenGL交互的类
inline void applyModelViewMatrix(const osg::RefMatrix* matrix)
{
if (_modelView!=matrix)
{
if (matrix)
{
_modelView=matrix;
glLoadMatrix(matrix->ptr());
}
else
{
_modelView=_identity;
glLoadIdentity();
}
}
}
它是直接使用glLoadMatrix(matrix)进行载入矩阵的.因此它的转置刚好适应了OpenGL列优先的模式.
你只需牢记 在OSG当中变换的步骤则是左乘操作(全局坐标系)..即左边的是先执行变换的.
谈完如上的那些之后.我们现在来看MatrixTransform 和PositionAttitudeTransform.
参考坐标系有三种
RELATIVE_RF, //全局 相对 ()
ABSOLUTE_RF, //局部 绝对 ()
ABSOLUTE_RF_INHERIT_VIEWPOINT //基于视点一个局部坐标系.很少用到.
MatrixTransform 故名 矩阵变换节点.在位于它的节点之下的节点都将按照这它的矩阵变换来进行模型变换操作.因此 MatrixTransform的主要功能之一就是提供模型变换操作..你只要根据你所需要的设置其模型矩阵就行.
即执行 setMatrix() 因此.查看计算当前World矩阵的方法就可以很清晰的明白其最后结果就是:
如果是相对的.那么 先执行自身的变换,在执行父节点的变换操作.这类似OpenGL中后写的变换是先执行的一样(全局坐标系考虑)
否则是绝对的,那么当前矩阵就是自身矩阵
bool MatrixTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
if (_referenceFrame==RELATIVE_RF)
{
matrix.preMult(_matrix);
}
else // absolute
{
matrix = _matrix;
}
return true;
}
PositionAttibuteTransform 就是位置姿态节点..即我们只可以调整该节点的所有孩子的位置以及姿态.,我们也先来看一下它的矩阵变换:
bool PositionAttitudeTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
if (_referenceFrame==RELATIVE_RF)
{
matrix.preMultTranslate(_position);
matrix.preMultRotate(_attitude);
matrix.preMultScale(_scale);
matrix.preMultTranslate(-_pivotPoint);
}
else // absolute
{
matrix.makeRotate(_attitude);
matrix.postMultTranslate(_position);
matrix.preMultScale(_scale);
matrix.preMultTranslate(-_pivotPoint);
}
return true;
}
PositionAttibuteTransform 的矩阵变换顺序的固定的.可以说是MatrixTransform的一个特例.,操作顺序我就不在详谈了.因为它的功能就是为了实现姿态和位置.还有缩放等.
因此 setPivotPoint 将使得之后的变换将会基于此平移操作执行.
那么实现一个例子来观察他们的效果: 下面的例子则是
<1> 使用PositionAttitudeTransform 设置左边的牛. 位置位于(-10,0,0) 姿态为绕z轴旋转90度.
<2> 使用MatrixTransform 设置右边的牛, 先执行平移操作(10,0,0) 在绕z轴旋转60度 因此使得这只牛偏屏幕内部一点.(你画个坐标轴 按全局思路演示 则就知道牛在上面位置了.!)
osg::Node* createTrans()
{
/** declare a root node*/
osg::Group* root = new osg::Group;
/** declare a Position Node*/
osg::PositionAttitudeTransform* posCow = new osg::PositionAttitudeTransform;
root->addChild(posCow);
/** declare a Matrix Node*/
osg::MatrixTransform* matrixCow = new osg::MatrixTransform;
root->addChild(matrixCow);
osg::Node* cow = osgDB::readNodeFile("cow.osg");
/**
When use Position Node and the ReferenceFrame is RELATIVE_RF
the matrix is Compute Trans(-pivot) * scale * Rotate * Trans(Pos)
here the pivot and scale is default,so it means that make rotate firstly.
*/
posCow->addChild(cow);
osg::Quat quat;
quat.makeRotate(osg::PI_2,osg::Vec3(0.0,0.0,1.0));
posCow->setAttitude(quat);
posCow->setPosition(osg::Vec3(-,0.0,0.0));
/**
when use Matrix Node you can set the matrix what you want.
here , it make trans firstly and then make rotate.
*/
matrixCow->addChild(cow);
quat.makeRotate(osg::DegreesToRadians(60.0),osg::Vec3(0.0,0.0,1.0));
matrixCow->setMatrix(osg::Matrixd::translate(osg::Vec3(10.0,0.0,0.0))*osg::Matrixd::rotate(quat));
return root;
}
OSG世界坐标转屏幕坐标(转载)的更多相关文章
- Unity 坐标 转换 详解 World世界坐标 Screen屏幕坐标 View视口坐标 GUI坐标 NGUI坐标 localPosition相对父级坐标
在制作游戏中我们经常会遇到这样一个需求: 在人物模型的上面显示 名字.称号 一类的文字或者图片 如下图 人物模型属于是Camera1 UI Title信息属于NGUI Camera2 如下图 这时 ...
- threejs 世界坐标与屏幕坐标相互转换
屏幕坐标转世界坐标: let pX = (screenPoint.x / this.scene.renderer.domElement.clientWidth) * 2 - 1; let pY = - ...
- Layabox 世界坐标和屏幕坐标互转
最近在入坑Layabox,花了几天时间做世界坐标和屏幕坐标的互转,由于Layabox没有现成的代码所以只能自己手动写,大概就是模仿unity里面的ScreenToWorldPoint和WorldToS ...
- OSG开发概览(转载)
OSG开发概览 1 OSG基础知识 Ø OSG是Open Scene Graphic 的缩写,OSG于1997年诞生于以为滑翔机爱好者之手,Don burns 为了对滑翔机的飞行进行模拟,对open ...
- ogre世界坐标鱼屏幕坐标相互转换
bool worldCoordToScreen(Vector3 objPos, Camera* cam, Vector2 screenRect, Vector2& screenPos) { ...
- threejs 世界坐标转化为屏幕坐标
网站: http://www.yanhuangxueyuan.com/Three.js_course/screen.html 方法.project 通过Vector3对象的方法project,方法的参 ...
- u3d 楼梯,圆环,椭圆,直线运动。世界坐标。点击。U3d stair, ring, ellipse, linear motion.World coordinates.Click .
u3d 楼梯,圆环,椭圆,直线运动.世界坐标.点击. U3d stair, ring, ellipse, linear motion.World coordinates.Click . 作者:韩梦飞沙 ...
- 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 & 第一个Shader的书写
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...
- NGUI系列教程五(角色信息跟随)
在一些网络游戏中,我们常常可以看到角色的上方显示着角色的名称,等级,血量等信息.它们可以跟随角色移动,并且可以显示和隐藏.今天我们就来学习一下这些功能的实现方法.1. 新建unity工 程,导入NGU ...
随机推荐
- TCP/IP模型各个层次的功能和协议
层次名称 功 能 协 议 应用层 (Application Layer) 负责实现一切与应用程序相关的功能,对应OSI参考模型的上三层 FTP(文件传输协议) HTTP(超文本传输协议 ...
- HDU 5875 st+二分区间
题目大意:给你n个数,q次询问,每次询问区间[l, r],问a[i]%a[i + 1] % a[i + 2]...%a[j](j <= r)的值 思路:st预处理维护,再二分区间,复杂度n*(l ...
- '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "AttentionController" nib but the view outlet was not set.'
问题出现原因: 先创建控制器的.h与.m文件,后来创建了相应的xib文件,运行后出现这个问题. 解决办法:
- Python的import嵌套
[root@fuel ~]# vi /var/lib/docker/devicemapper/mnt/4da57a0078c9d3f32e819373b67de41da37c34a27ee03f740 ...
- 强制删除sql用户链接
SELECT 'alter system kill session '''||sid||','||serial#||''';' FROM v$session WHERE username='USER' ...
- win7 以管理员身份运行cmd, windows services 的创建和删除
以 http 协议访问svn repository 搭建可用http访问的svn(windows) http://blog.csdn.net/yangyangrenren/article/detail ...
- ural1003 Parity
Parity Time limit: 2.0 secondMemory limit: 64 MB Now and then you play the following game with your ...
- DHCP详解
概述 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分 ...
- Javascript Jquery 中的数组定义与操作_子木玲_新浪博客
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- CentOS 6.4 x64 zabbix 2.2.2 编译安装
A. 服务端安装配置 1.下载zabbix 2.x 最新版本 http://www.zabbix.com/download.php 2.安装配置所需要软件(zabbix需要一个lamp环境) 使用 y ...