geom.cc
来自「机器人人3D仿真工具,可以加入到Simbad仿真环境下应用。」· CC 代码 · 共 650 行
CC
650 行
/* * Gazebo - Outdoor Multi-Robot Simulator * Copyright (C) 2003 * Nate Koenig & Andrew Howard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *//* Desc: Base class for all drawables * Author: Nate Keonig * Date: 04 May 2003 * CVS: $Id: Geom.cc,v 1.45 2005/03/18 23:19:58 natepak Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <assert.h>#include <stdint.h>#include <math.h>#include <GL/glu.h>#include "Error.hh"#include "Vector.hh"#include "Image.hh"#include "Body.hh"#include "Geom.hh"#if HAVE_LIB3DS#include <lib3ds/file.h>#include <lib3ds/node.h>#include <lib3ds/mesh.h>#include <lib3ds/vector.h>#include <lib3ds/matrix.h>#include <lib3ds/material.h>#endif//////////////////////////////////////////////////////////////////////////////// ConstructorGeom::Geom(dSpaceID spaceId) : BaseGeom(spaceId){ this->renderOrder = GZ_RENDER_OPAQUE; this->transparency = false; this->laser = 1; this->retro = 0.0; this->fiducial = -1; // Initial color this->SetAmbientColor( GzColor( 0.2, 0.2, 0.2, 1.0 ) ); this->SetDiffuseColor( GzColor( 0.8, 0.8, 0.8, 1.0 ) ); this->SetSpecularColor( GzColor( 0.2, 0.2, 0.2, 1.0 ) ); this->SetEmissionColor( GzColor( 0, 0, 0, 1.0 ) ); this->textureImage = NULL; this->textureSize = GzVectorSet(2.0, 2.0, 2.0); this->skinFile = NULL; this->skinNull = false; this->skinScale = GzVectorSet(1, 1, 1); this->skinPose = GzPoseSet(GzVectorZero(), GzQuaternIdent()); memset(this->listList, 0, sizeof(this->listList)); return;}//////////////////////////////////////////////////////////////////////////////// DestructorGeom::~Geom(){ if (this->textureImage) delete this->textureImage;#ifdef HAVE_LIB3DS if (this->skinFile) lib3ds_file_free(this->skinFile);#endif return;}//////////////////////////////////////////////////////////////////////////////// Set ambient, diffuse, and specular to the same colorvoid Geom::SetColor( const GzColor &color ){ this->dirty = true; this->SetAmbientColor(GzColor(color.r*.2, color.g*.2, color.b*.2)); this->SetDiffuseColor(color); this->SetSpecularColor(GzColor(color.r*1.2, color.g*1.2, color.b*1.2));}//////////////////////////////////////////////////////////////////////////////// Set the ambient colorvoid Geom::SetAmbientColor( const GzColor &color ){ this->dirty = true; GZ_COLOR_COPY(this->colorAmbient, color); return;}//////////////////////////////////////////////////////////////////////////////// Set the diffuse colorvoid Geom::SetDiffuseColor( const GzColor &color ){ this->dirty = true; GZ_COLOR_COPY(this->colorDiffuse, color); return;}//////////////////////////////////////////////////////////////////////////////// Set the specular colorvoid Geom::SetSpecularColor( const GzColor &color ){ this->dirty = true; GZ_COLOR_COPY(this->colorSpecular, color); return;}//////////////////////////////////////////////////////////////////////////////// Set the emission colorvoid Geom::SetEmissionColor( const GzColor &color ){ this->dirty = true; GZ_COLOR_COPY(this->colorEmission, color); return;}//////////////////////////////////////////////////////////////////////////////// Set the 2D texture.int Geom::SetTexture2D( int width, int height, const uint8_t *data ){ this->dirty = true; if (this->textureImage != NULL) delete this->textureImage; this->textureImage = new GzImage; if (this->textureImage->Set(width, height, data) != 0) return -1; return 0;}//////////////////////////////////////////////////////////////////////////////// Set the 2D texture (accepts NULL for no texture)int Geom::SetTexture2DFile( const char *filename ){ this->dirty = true; if (this->textureImage) { delete this->textureImage; this->textureImage = NULL; } if (filename == NULL) return 0; this->textureImage = new GzImage; if (this->textureImage->Load(filename) != 0) { delete this->textureImage; this->textureImage = NULL; return -1; } return 0;}//////////////////////////////////////////////////////////////////////////////// Set size of the texture image when mapped on a geom.void Geom::SetTexture2DSize( GzVector size ){ this->dirty = true; this->textureSize = size; return;}//////////////////////////////////////////////////////////////////////////////// Set the visual skin (3DS format)int Geom::SetSkinFile( const char *filename ){#if HAVE_LIB3DS this->dirty = true; // Load the skin file skinFile = lib3ds_file_load(filename); if (skinFile == NULL) { PRINT_WARN1("could not load [%s]", filename); return -1; } // Get the first frame lib3ds_file_eval(this->skinFile, 0); return 0;#else PRINT_WARN("support for skins was disabled at compile time"); return 0;#endif }//////////////////////////////////////////////////////////////////////////////// Set the skin posevoid Geom::SetSkinPose( GzPose pose ){ this->dirty = true; this->skinPose = pose; return;}//////////////////////////////////////////////////////////////////////////////// Set the skin scalevoid Geom::SetSkinScale( GzVector scale ){ this->dirty = true; this->skinScale = scale; return;}//////////////////////////////////////////////////////////////////////////////// Set the Shade Modelvoid Geom::SetShadeModel( const char *mode ){ this->dirty = true; // TODO return;}//////////////////////////////////////////////////////////////////////////////// Set the Polygon Modevoid Geom::SetPolygonMode( const char *mode ){ this->dirty = true; // TODO return;}//////////////////////////////////////////////////////////////////////////////// Set the transparencyvoid Geom::SetTransparency( bool enable ){ this->dirty = true; this->transparency = enable; if (this->transparency) this->renderOrder = GZ_RENDER_TRANSPARENT; else this->renderOrder = GZ_RENDER_OPAQUE; return;}//////////////////////////////////////////////////////////////////////////////// Set the shininessvoid Geom::SetShininess( float num ){ this->dirty = true; this->shininess = num; return;}//////////////////////////////////////////////////////////////////////////////// Set the laser-reflectivenessvoid Geom::SetLaser( float num ){ this->laser = num; return;}//////////////////////////////////////////////////////////////////////////////// Set the retro-reflectivenessvoid Geom::SetRetro( float num ){ this->retro = num; return;}//////////////////////////////////////////////////////////////////////////////// Set the fiducial idvoid Geom::SetFiducial( int id ){ this->fiducial = id; return;}//////////////////////////////////////////////////////////////////////////////// Set the pick id. Allows a user to select an object with the mousevoid Geom::SetPickId( GLuint id ){ this->pick = id; return;}//////////////////////////////////////////////////////////////////////////////// Get the ambient colorGzColor Geom::GetAmbientColor() const{ return GzColor(this->colorAmbient[0], this->colorAmbient[1], this->colorAmbient[2], this->colorAmbient[3]);}//////////////////////////////////////////////////////////////////////////////// Get the diffuse factorGzColor Geom::GetDiffuseColor() const{ return GzColor(this->colorDiffuse[0], this->colorDiffuse[1], this->colorDiffuse[2], this->colorDiffuse[3]);}//////////////////////////////////////////////////////////////////////////////// Get the specular factorGzColor Geom::GetSpecularColor() const{ return GzColor(this->colorSpecular[0], this->colorSpecular[1], this->colorSpecular[2], this->colorSpecular[3]);}//////////////////////////////////////////////////////////////////////////////// Get the transparencyfloat Geom::GetTransparency() const{ return this->transparency;}//////////////////////////////////////////////////////////////////////////////// Get the shininessfloat Geom::GetShininess() const{ return this->shininess;}//////////////////////////////////////////////////////////////////////////////// Get the laser-reflectivenessfloat Geom::GetLaser() const{ return this->laser;}//////////////////////////////////////////////////////////////////////////////// Get the retor-reflectivenessfloat Geom::GetRetro() const{ return this->retro;}//////////////////////////////////////////////////////////////////////////////// Get the fiducial idint Geom::GetFiducial() const{ return this->fiducial;}//////////////////////////////////////////////////////////////////////////////// Get the pick idGLuint Geom::GetPickId() const{ return this->pick;}///////////////////////////////////////////////////////////////////////////////// @brief Set stored list options for a particular cameravoid Geom::SetList(int camera, GLuint listId, RenderOptions opt){ assert(camera >= 0); assert(camera < (int) (sizeof(this->listList) / sizeof(this->listList[0]))); this->listList[camera].listId = listId; this->listList[camera].opt = opt; return;}///////////////////////////////////////////////////////////////////////////////// @brief Get stored list options for a particular cameravoid Geom::GetList(int camera, GLuint *listId, RenderOptions *opt){ assert(camera >= 0); assert(camera < (int) (sizeof(this->listList) / sizeof(this->listList[0]))); *listId = this->listList[camera].listId; *opt = this->listList[camera].opt; return;}//////////////////////////////////////////////////////////////////////////////// Pre-renderervoid Geom::PreRender(RenderOptions *opt){ GzPose pose; GzVector pos; GzQuatern rot; glPushMatrix(); // This tags the next drawn object the the "pick" id. // This call only doesn't something meaningful when // glRenderMode(GL_SELECT) glPushName(this->pick); // Get global object pose pose = this->GetPose(); // Apply translation pos = pose.pos; glTranslatef(pos.x, pos.y, pos.z); // Apply rotation rot = GzQuaternToAxis(pose.rot); glRotatef(rot.u * 180 / M_PI, rot.x, rot.y, rot.z); return;}//////////////////////////////////////////////////////////////////////////////// Default render routinevoid Geom::Render(RenderOptions *opt){ return;}//////////////////////////////////////////////////////////////////////////////// Post-renderervoid Geom::PostRender(RenderOptions *opt){ this->dirty = false; glPopName(); glPopMatrix(); return;}//////////////////////////////////////////////////////////////////////////////// Render the skinvoid Geom::RenderSkin(RenderOptions *opt){ #ifdef HAVE_LIB3DS GzVector pos; GzQuatern rot; Lib3dsNode *p; Lib3dsMesh *m; if (this->skinFile == NULL) return; // Need normalization for rescaled models glEnable(GL_NORMALIZE); // Apply translation pos = this->skinPose.pos; glTranslatef(pos.x, pos.y, pos.z); // Apply rotation rot = GzQuaternToAxis(this->skinPose.rot); glRotatef(rot.u * 180 / M_PI, rot.x, rot.y, rot.z); // Apply scaling glScalef(this->skinScale.x, this->skinScale.y, this->skinScale.z); if (this->skinFile->nodes != NULL) for (p = this->skinFile->nodes; p != NULL; p = p->next) this->RenderSkinNode(p); else if (this->skinFile->meshes != NULL) { //if (this->meshListId == 0) //{ //this->meshListId = glGenLists(1); //glNewList(this->meshListId, GL_COMPILE); for (m=this->skinFile->meshes; m!=NULL; m = m->next) this->RenderSkinMesh(m); //glEndList(); //} /*if (this->meshListId) { Render the object glCallList(this->meshListId); }*/ }#endif return;}//////////////////////////////////////////////////////////////////////////////// Render a node (recursive)void Geom::RenderSkinNode(Lib3dsNode *node){#ifdef HAVE_LIB3DS Lib3dsNode *p; Lib3dsMesh *mesh; // Render the children first for (p = node->childs; p != 0; p = p->next) this->RenderSkinNode(p); if (node->type != LIB3DS_OBJECT_NODE) return; if (strcmp(node->name,"$$$DUMMY") == 0) return; // If we dont have a display list yet, create one /*if (node->user.d == 0) { // TODO: this may clash with our list id assignment; FIX node->user.d = glGenLists(1); glNewList(node->user.d, GL_COMPILE); mesh = lib3ds_file_mesh_by_name(this->skinFile, node->name); assert(mesh); this->RenderSkinMesh( mesh ); glEndList(); }*/ // If we do have a display list, render it //if (node->user.d) //{ Lib3dsObjectData *d; glPushMatrix(); // Apply translations from file d = &node->data.object; glMultMatrixf(&node->matrix[0][0]); glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]); mesh = lib3ds_file_mesh_by_name(this->skinFile, node->name); assert(mesh); this->RenderSkinMesh( mesh ); // Render the object //glCallList(node->user.d); glPopMatrix(); //}#endif return;}//////////////////////////////////////////////////////////////////////////////// Render a mesh void Geom::RenderSkinMesh( Lib3dsMesh *mesh ){#ifdef HAVE_LIB3DS unsigned p; Lib3dsVector *normalL=(Lib3dsVector *) malloc(3*sizeof(Lib3dsVector)*mesh->faces); { Lib3dsMatrix M; lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[0][0]); } lib3ds_mesh_calculate_normals(mesh, normalL); for (p=0; p<mesh->faces; ++p) { Lib3dsFace *f=&mesh->faceL[p]; Lib3dsMaterial *mat=0; if (f->material[0]) { mat=lib3ds_file_material_by_name(this->skinFile, f->material); } if (mat) { static GLfloat a[4]={0,0,0,1}; float s; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); s = pow(2, 10.0*mat->shininess); if (s>128.0) { s=128.0; } glMaterialf(GL_FRONT, GL_SHININESS, s); } else { Lib3dsRgba a={0.2, 0.2, 0.2, 1.0}; Lib3dsRgba d={0.8, 0.8, 0.8, 1.0}; Lib3dsRgba s={0.0, 0.0, 0.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); } { int i; glBegin(GL_TRIANGLES); glNormal3fv(f->normal); for (i=0; i<3; ++i) { glNormal3fv(normalL[3*p+i]); glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); } } free(normalL);#endif return;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?