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 ...
随机推荐
- linux shell: 取得某个目录下的文件名列表
取得某个目录下文件名的列表(没有子目录) ls -l dir/ | awk '{print "dir\\" $9}' #其中$9是ls -l 的第9个字段-文件名
- apache RewriteCond RewriteRule
http://www.rockbb.com/blog/?p=319 http://www.cnblogs.com/scgw/archive/2011/12/10/2283029.html 我的理解:当 ...
- Android平台中实现对XML的三种解析方式
本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...
- HDU 1789 Doing Homework again(贪心)
在我上一篇说到的,就是这个,贪心的做法,对比一下就能发现,另一个的扣分会累加而且最后一定是把所有的作业都做了,而这个扣分是一次性的,所以应该是舍弃扣分小的,所以结构体排序后,往前选择一个损失最小的方案 ...
- ASP.NET WebService
一.WebService:WebService是以独立于平台的方式,通过标准的Web协议,可以由程序访问的应用程序逻辑单元. (1)应用程序逻辑单元:web服务包括一些应用程序逻辑单元或者代码.这些代 ...
- Qt5:QSystemTrayIcon类实现程序托盘图标
windows下,在许多应用程序中都会实现一个托盘图标,用于隐藏应用程序窗口时还能对该应用程序进行简单的操作,例如 QQ ,renren等程序 那么,在Qt中,如何实现呢? 这就要用到Qt提供的 QS ...
- VS2012添加对DirectX SDK中需要文件的引用
error LNK2019: 无法解析的外部符号 _DirectDrawCreateEx@16,该符号在函数 "int __cdecl DD_Init(int,int,int)" ...
- docker k8s 1.3.8 + flannel
docker k8s + flannel kubernetes 是谷歌开源的 docker 集群管理解决方案. 项目地址: http://kubernetes.io/ 测试环境: node-1: 10 ...
- Android学习笔记之Intent(2)
打开网页 package com.jiahemeikang.helloandroid; import java.io.File; import com.jiahemikang.service.Echo ...
- PAT (Advanced Level) 1007. Maximum Subsequence Sum (25)
简单DP. 注意:If all the K numbers are negative, then its maximum sum is defined to be 0, and you are sup ...