Code cleanup:

* Remove BSP_GhostTest, not used and working for ages, approved by Sergey.
This commit is contained in:
Thomas Dinges
2012-08-04 11:42:38 +00:00
parent f50bae3259
commit 2390c95cf1
12 changed files with 0 additions and 4819 deletions

View File

@@ -1,126 +0,0 @@
# Microsoft Developer Studio Project File - Name="BSP_GhostTest" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=BSP_GhostTest - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "BSP_GhostTest.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "BSP_GhostTest.mak" CFG="BSP_GhostTest - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "BSP_GhostTest - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "BSP_GhostTest - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "BSP_GhostTest - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /Ob2 /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x413 /d "NDEBUG"
# ADD RSC /l 0x413 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 glu32.lib opengl32.lib kernel32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\"
!ELSEIF "$(CFG)" == "BSP_GhostTest - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../extern/" /I "../../../../lib/windows/string/include" /I "../../../../lib/windows/ghost/include" /I "../../../../lib/windows/moto/include" /I "../../../../lib/windows/memutil/include" /I "../../../../lib/windows/container/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x413 /d "_DEBUG"
# ADD RSC /l 0x413 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\lib\windows\glut-3.7\lib\\"
!ENDIF
# Begin Target
# Name "BSP_GhostTest - Win32 Release"
# Name "BSP_GhostTest - Win32 Debug"
# Begin Source File
SOURCE=.\BSP_GhostTest3D.cpp
# End Source File
# Begin Source File
SOURCE=.\BSP_GhostTest3D.h
# End Source File
# Begin Source File
SOURCE=.\BSP_MeshDrawer.cpp
# End Source File
# Begin Source File
SOURCE=.\BSP_MeshDrawer.h
# End Source File
# Begin Source File
SOURCE=.\BSP_PlyLoader.cpp
# End Source File
# Begin Source File
SOURCE=.\BSP_PlyLoader.h
# End Source File
# Begin Source File
SOURCE=.\BSP_TMesh.h
# End Source File
# Begin Source File
SOURCE=.\main.cpp
# End Source File
# Begin Source File
SOURCE=.\ply.h
# End Source File
# Begin Source File
SOURCE=.\plyfile.c
# End Source File
# End Target
# End Project

View File

@@ -1,125 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "BSP_GhostTest"=.\BSP_GhostTest.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name bsplib
End Project Dependency
Begin Project Dependency
Project_Dep_Name ghost
End Project Dependency
Begin Project Dependency
Project_Dep_Name string
End Project Dependency
Begin Project Dependency
Project_Dep_Name MoTo
End Project Dependency
}}}
###############################################################################
Project: "MoTo"=..\..\..\moto\make\msvc_6_0\MoTo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "bsplib"=..\..\make\msvc6_0\bsplib.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name container
End Project Dependency
Begin Project Dependency
Project_Dep_Name memutil
End Project Dependency
Begin Project Dependency
Project_Dep_Name MoTo
End Project Dependency
}}}
###############################################################################
Project: "container"=..\..\..\container\make\msvc_6_0\container.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name memutil
End Project Dependency
}}}
###############################################################################
Project: "ghost"=..\..\..\ghost\make\msvc\ghost.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "memutil"=..\..\..\memutil\make\msvc_60\memutil.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "string"=..\..\..\string\make\msvc_6_0\string.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -1,649 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/**
* Copyright (C) 2001 NaN Technologies B.V.
*/
#if defined(WIN32) || defined(__APPLE__)
# ifdef WIN32
# include <windows.h>
# include <GL/gl.h>
# include <GL/glu.h>
# else // WIN32
# include <AGL/gl.h>
# endif // WIN32
#else // defined(WIN32) || defined(__APPLE__)
# include <GL/gl.h>
# include <GL/glu.h>
#endif // defined(WIN32) || defined(__APPLE__)
#include "BSP_GhostTest3D.h"
#include "BSP_MeshDrawer.h"
#include "GHOST_ISystem.h"
#include "GHOST_IWindow.h"
#include "MT_Quaternion.h"
#include "MT_Transform.h"
#include "CSG_BooleanOps.h"
#include <iostream>
int
EmptyInterpFunc(
void *d1,
void * d2,
void *dnew,
float epsilon
){
return 0;
}
using namespace std;
BSP_GhostTestApp3D::
BSP_GhostTestApp3D(
) :
m_window(NULL),
m_system(NULL),
m_finish_me_off(false),
m_current_object(0)
{
//nothing to do;
}
void
BSP_GhostTestApp3D::
SetMesh(
MEM_SmartPtr<BSP_TMesh> mesh
){
m_meshes.push_back(mesh);
BSP_RotationSetting rotation_setting;
BSP_TranslationSetting translation_setting;
rotation_setting.m_angle_x = MT_Scalar(0);
rotation_setting.m_angle_y = MT_Scalar(0);
rotation_setting.m_moving = false;
rotation_setting.x_old = 0;
rotation_setting.y_old = 0;
translation_setting.m_t_x = MT_Scalar(0);
translation_setting.m_t_y = MT_Scalar(0);
translation_setting.m_t_z = MT_Scalar(0);
translation_setting.m_moving = false;
translation_setting.x_old = 0;
translation_setting.y_old = 0;
m_rotation_settings.push_back(rotation_setting);
m_translation_settings.push_back(translation_setting);
m_render_modes.push_back(e_wireframe_shaded);
m_scale_settings.push_back(MT_Scalar(1));
}
void
BSP_GhostTestApp3D::
Swap(
int i
){
if (!m_rotation_settings[i].m_moving && !m_translation_settings[i].m_moving) {
swap(m_meshes[i],m_meshes.back());
swap(m_rotation_settings[i],m_rotation_settings.back());
swap(m_translation_settings[i],m_translation_settings.back());
swap(m_scale_settings[i],m_scale_settings.back());
swap(m_render_modes[i],m_render_modes.back());
}
}
MT_Transform
BSP_GhostTestApp3D::
GetTransform(
int i
){
MT_Quaternion q_ax(MT_Vector3(0,1,0),m_rotation_settings[i].m_angle_x);
MT_Quaternion q_ay(MT_Vector3(1,0,0),m_rotation_settings[i].m_angle_y);
MT_Point3 tr(
m_translation_settings[i].m_t_x,
m_translation_settings[i].m_t_y,
m_translation_settings[i].m_t_z
);
MT_Matrix3x3 rotx(q_ax);
MT_Matrix3x3 roty(q_ay);
MT_Matrix3x3 rot = rotx * roty;
MT_Transform trans(tr,rot);
MT_Transform scalet;
scalet.setIdentity();
scalet.scale(m_scale_settings[i],m_scale_settings[i],m_scale_settings[i]);
return trans * scalet;
}
void
BSP_GhostTestApp3D::
Operate(
int type
){
CSG_VertexIteratorDescriptor * vA = VertexIt_Construct(m_meshes[0],GetTransform(0));
CSG_FaceIteratorDescriptor * fA = FaceIt_Construct(m_meshes[0]);
CSG_VertexIteratorDescriptor * vB = VertexIt_Construct(m_meshes[1],GetTransform(1));
CSG_FaceIteratorDescriptor * fB = FaceIt_Construct(m_meshes[1]);
// describe properties.
CSG_MeshPropertyDescriptor props;
props.user_face_vertex_data_size = 0;
props.user_data_size = 0;
CSG_BooleanOperation * op = CSG_NewBooleanFunction();
props = CSG_DescibeOperands(op,props,props);
CSG_PerformBooleanOperation(
op,CSG_OperationType(type),
*fA,*vA,*fB,*vB,EmptyInterpFunc
);
CSG_FaceIteratorDescriptor out_f;
CSG_OutputFaceDescriptor(op,&out_f);
CSG_VertexIteratorDescriptor out_v;
CSG_OutputVertexDescriptor(op,&out_v);
MEM_SmartPtr<BSP_TMesh> new_mesh (BuildMesh(props,out_f,out_v));
// free stuff
CSG_FreeVertexDescriptor(&out_v);
CSG_FreeFaceDescriptor(&out_f);
CSG_FreeBooleanOperation(op);
op = NULL;
SetMesh(new_mesh);
}
void
BSP_GhostTestApp3D::
UpdateFrame(
) {
if (m_window) {
GHOST_Rect v_rect;
m_window->getClientBounds(v_rect);
glViewport(0,0,v_rect.getWidth(),v_rect.getHeight());
}
}
MT_Vector3
BSP_GhostTestApp3D::
UnProject(
const MT_Vector3 & vec
) {
GLint viewport[4];
GLdouble mvmatrix[16],projmatrix[16];
glGetIntegerv(GL_VIEWPORT,viewport);
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
GLdouble realy = viewport[3] - vec.y() - 1;
GLdouble outx,outy,outz;
gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz);
return MT_Vector3(outx,outy,outz);
}
bool
BSP_GhostTestApp3D::
InitApp(
){
// create a system and window with opengl
// rendering context.
GHOST_TSuccess success = GHOST_ISystem::createSystem();
if (success == GHOST_kFailure) return false;
m_system = GHOST_ISystem::getSystem();
if (m_system == NULL) return false;
m_system->addEventConsumer(this);
m_window = m_system->createWindow(
"GHOST crud3D!",
100,100,512,512,GHOST_kWindowStateNormal,
GHOST_kDrawingContextTypeOpenGL,false
);
if (
m_window == NULL
) {
m_system = NULL;
GHOST_ISystem::disposeSystem();
return false;
}
// make an opengl frustum for this wind
MT_Vector3 min,max;
min = m_meshes[0]->m_min;
max = m_meshes[0]->m_max;
InitOpenGl(min,max);
return true;
}
void
BSP_GhostTestApp3D::
Run(
){
if (m_system == NULL) {
return;
}
while (!m_finish_me_off) {
m_system->processEvents(true);
m_system->dispatchEvents();
};
}
bool
BSP_GhostTestApp3D::
processEvent(
GHOST_IEvent* event
){
bool handled = false;
switch(event->getType()) {
case GHOST_kEventWindowSize:
case GHOST_kEventWindowActivate:
UpdateFrame();
case GHOST_kEventWindowUpdate:
DrawPolies();
handled = true;
break;
case GHOST_kEventButtonDown:
{
int x,y;
m_system->getCursorPosition(x,y);
int wx,wy;
m_window->screenToClient(x,y,wx,wy);
GHOST_TButtonMask button =
static_cast<GHOST_TEventButtonData *>(event->getData())->button;
if (button == GHOST_kButtonMaskLeft) {
m_rotation_settings[m_current_object].m_moving = true;
m_rotation_settings[m_current_object].x_old = x;
m_rotation_settings[m_current_object].y_old = y;
} else
if (button == GHOST_kButtonMaskRight) {
m_translation_settings[m_current_object].m_moving = true;
m_translation_settings[m_current_object].x_old = x;
m_translation_settings[m_current_object].y_old = y;
} else
m_window->invalidate();
handled = true;
break;
}
case GHOST_kEventButtonUp:
{
GHOST_TButtonMask button =
static_cast<GHOST_TEventButtonData *>(event->getData())->button;
if (button == GHOST_kButtonMaskLeft) {
m_rotation_settings[m_current_object].m_moving = false;
m_rotation_settings[m_current_object].x_old = 0;
m_rotation_settings[m_current_object].y_old = 0;
} else
if (button == GHOST_kButtonMaskRight) {
m_translation_settings[m_current_object].m_moving = false;
m_translation_settings[m_current_object].x_old;
m_translation_settings[m_current_object].y_old;
}
m_window->invalidate();
handled = true;
break;
}
case GHOST_kEventCursorMove:
{
int x,y;
m_system->getCursorPosition(x,y);
int wx,wy;
m_window->screenToClient(x,y,wx,wy);
if (m_rotation_settings[m_current_object].m_moving) {
m_rotation_settings[m_current_object].m_angle_x = MT_Scalar(wx)/20;
m_rotation_settings[m_current_object].x_old = wx;
m_rotation_settings[m_current_object].m_angle_y = MT_Scalar(wy)/20;
m_rotation_settings[m_current_object].y_old = wy;
m_window->invalidate();
}
if (m_translation_settings[m_current_object].m_moving) {
// project current objects bounding box center into screen space.
// unproject mouse point into object space using z-value from
// projected bounding box center.
GHOST_Rect bounds;
m_window->getClientBounds(bounds);
int w_h = bounds.getHeight();
y = w_h - wy;
x = wx;
double mvmatrix[16];
double projmatrix[16];
GLint viewport[4];
double px, py, pz,sz;
/* Get the matrices needed for gluUnProject */
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
// work out the position of the end effector in screen space
GLdouble ex,ey,ez;
ex = m_translation_settings[m_current_object].m_t_x;
ey = m_translation_settings[m_current_object].m_t_y;
ez = m_translation_settings[m_current_object].m_t_z;
gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
m_translation_settings[m_current_object].m_t_x = px;
m_translation_settings[m_current_object].m_t_y = py;
m_translation_settings[m_current_object].m_t_z = pz;
m_window->invalidate();
}
handled = true;
break;
}
case GHOST_kEventKeyDown :
{
GHOST_TEventKeyData *kd =
static_cast<GHOST_TEventKeyData *>(event->getData());
switch(kd->key) {
case GHOST_kKeyI:
{
// now intersect meshes.
Operate(e_csg_intersection);
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyU:
{
Operate(e_csg_union);
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyD:
{
Operate(e_csg_difference);
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyA:
{
m_scale_settings[m_current_object] *= 1.1;
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyZ:
{
m_scale_settings[m_current_object] *= 0.8;
handled = true;
m_window->invalidate();
break;
}
case GHOST_kKeyR:
m_render_modes[m_current_object]++;
if (m_render_modes[m_current_object] > e_last_render_mode) {
m_render_modes[m_current_object] = e_first_render_mode;
}
handled = true;
m_window->invalidate();
break;
case GHOST_kKeyB:
handled = true;
m_window->invalidate();
break;
case GHOST_kKeyQ:
m_finish_me_off = true;
handled = true;
break;
case GHOST_kKeyS:
Swap(m_current_object);
m_window->invalidate();
handled = true;
break;
case GHOST_kKeySpace:
// increment the current object only if the object is not being
// manipulated.
if (! (m_rotation_settings[m_current_object].m_moving || m_translation_settings[m_current_object].m_moving)) {
m_current_object ++;
if (m_current_object >= m_meshes.size()) {
m_current_object = 0;
}
}
m_window->invalidate();
handled = true;
break;
default :
break;
}
}
default :
break;
}
return handled;
};
BSP_GhostTestApp3D::
~BSP_GhostTestApp3D(
){
if (m_window) {
m_system->disposeWindow(m_window);
m_window = NULL;
GHOST_ISystem::disposeSystem();
m_system = NULL;
}
};
void
BSP_GhostTestApp3D::
DrawPolies(
){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < m_meshes.size(); ++i) {
MT_Transform trans = GetTransform(i);
float opengl_mat[16];
trans.getValue(opengl_mat);
glPushMatrix();
glMultMatrixf(opengl_mat);
MT_Vector3 color(1.0,1.0,1.0);
if (i == m_current_object) {
color = MT_Vector3(1.0,0,0);
}
BSP_MeshDrawer::DrawMesh(m_meshes[i].Ref(),m_render_modes[i]);
glPopMatrix();
}
m_window->swapBuffers();
}
void
BSP_GhostTestApp3D::
InitOpenGl(
const MT_Vector3 &min,
const MT_Vector3 &max
){
GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */
GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */
GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */
/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
// make sure there is no back face culling.
// glDisable(GL_CULL_FACE);
// use two sided lighting model
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
/* Use depth buffering for hidden surface elimination. */
glEnable(GL_DEPTH_TEST);
/* Setup the view of the cube. */
glMatrixMode(GL_PROJECTION);
// center of the box + 3* depth of box
MT_Vector3 center = (min + max) * 0.5;
MT_Vector3 diag = max - min;
float depth = diag.length();
float distance = 5;
gluPerspective(
/* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0,
/* Z far */ distance * depth * 2
);
glMatrixMode(GL_MODELVIEW);
gluLookAt(
center.x(), center.y(), center.z() + distance*depth, //eye
center.x(), center.y(), center.z(), //center
0.0, 1.0, 0.
); /* up is in positive Y direction */
}

View File

@@ -1,159 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BSP_GHOSTTEST3D_H__
#define __BSP_GHOSTTEST3D_H__
#include "GHOST_IEventConsumer.h"
#include "MT_Vector3.h"
#include "BSP_TMesh.h"
#include "BSP_MeshDrawer.h"
#include <vector>
class GHOST_IWindow;
class GHOST_ISystem;
class BSP_GhostTestApp3D :
public GHOST_IEventConsumer
{
public :
// Construct an instance of the application;
BSP_GhostTestApp3D(
);
// initialize the applicaton
bool
InitApp(
);
// Run the application untill internal return.
void
Run(
);
~BSP_GhostTestApp3D(
);
void
SetMesh(
MEM_SmartPtr<BSP_TMesh> mesh
);
private :
struct BSP_RotationSetting {
MT_Scalar m_angle_x;
MT_Scalar m_angle_y;
int x_old;
int y_old;
bool m_moving;
};
struct BSP_TranslationSetting {
MT_Scalar m_t_x;
MT_Scalar m_t_y;
MT_Scalar m_t_z;
int x_old;
int y_old;
bool m_moving;
};
// Return the transform of object i
MT_Transform
GetTransform(
int active_object
);
// Perform an operation between the first two objects in the
// list
void
Operate(
int type
);
// Swap mesh i and settings with the last mesh in list.
void
Swap(
int i
);
void
DrawPolies(
);
void
UpdateFrame(
);
MT_Vector3
UnProject(
const MT_Vector3 & vec
);
// Create a frustum and projection matrix to
// look at the bounding box
void
InitOpenGl(
const MT_Vector3 &min,
const MT_Vector3 &max
);
// inherited from GHOST_IEventConsumer
bool
processEvent(
GHOST_IEvent* event
);
GHOST_IWindow *m_window;
GHOST_ISystem *m_system;
bool m_finish_me_off;
// List of current meshes.
std::vector< MEM_SmartPtr<BSP_TMesh> > m_meshes;
std::vector< BSP_RotationSetting> m_rotation_settings;
std::vector< BSP_TranslationSetting> m_translation_settings;
std::vector< MT_Scalar> m_scale_settings;
std::vector< int> m_render_modes;
int m_current_object;
};
#endif

View File

@@ -1,156 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "BSP_MeshDrawer.h"
#include "BSP_TMesh.h"
#if defined(WIN32) || defined(__APPLE__)
# ifdef WIN32
# include <windows.h>
# include <GL/gl.h>
# include <GL/glu.h>
# else // WIN32
# include <AGL/gl.h>
# endif // WIN32
#else // defined(WIN32) || defined(__APPLE__)
# include <GL/gl.h>
# include <GL/glu.h>
#endif // defined(WIN32) || defined(__APPLE__)
#include <vector>
using namespace std;
void
BSP_MeshDrawer::
DrawMesh(
BSP_TMesh &mesh,
int render_mode
){
if (render_mode == e_none) return;
// decompose polygons into triangles.
glEnable(GL_LIGHTING);
if (render_mode == e_wireframe || render_mode == e_wireframe_shaded) {
glColor3f(0.0, 0.0, 0.0);
if (render_mode == e_wireframe) {
glDisable(GL_LIGHTING);
} else {
glEnable(GL_LIGHTING);
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0,1.0);
glBegin(GL_TRIANGLES);
DrawPolies(mesh);
glEnd();
glColor3f(1.0, 1.0, 1.0);
glDisable(GL_LIGHTING);
glDisable(GL_POLYGON_OFFSET_FILL);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_TRIANGLES);
DrawPolies(mesh);
glEnd();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} else {
glEnable(GL_LIGHTING);
glBegin(GL_TRIANGLES);
DrawPolies(mesh);
glEnd();
}
}
void
BSP_MeshDrawer::
DrawPolies(
BSP_TMesh &mesh
){
const vector<BSP_TVertex> & verts = mesh.VertexSet();
const vector<BSP_TFace> &faces = mesh.FaceSet();
// just draw the edges for now.
vector<BSP_TVertex>::const_iterator vertex_it = verts.begin();
vector<BSP_TFace>::const_iterator faces_it = faces.begin();
vector<BSP_TFace>::const_iterator faces_end = faces.end();
for (;faces_it != faces_end; ++faces_it ){
glNormal3f(
faces_it->m_normal.x(),
faces_it->m_normal.y(),
faces_it->m_normal.z()
);
glVertex3f(
verts[faces_it->m_verts[0]].m_pos.x(),
verts[faces_it->m_verts[0]].m_pos.y(),
verts[faces_it->m_verts[0]].m_pos.z()
);
glVertex3f(
verts[faces_it->m_verts[1]].m_pos.x(),
verts[faces_it->m_verts[1]].m_pos.y(),
verts[faces_it->m_verts[1]].m_pos.z()
);
glVertex3f(
verts[faces_it->m_verts[2]].m_pos.x(),
verts[faces_it->m_verts[2]].m_pos.y(),
verts[faces_it->m_verts[2]].m_pos.z()
);
}
}

View File

@@ -1,71 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BSP_MESHDRAWER_H__
#define __BSP_MESHDRAWER_H__
class BSP_TMesh;
class MT_Vector3;
enum BSP_TRenderMode {
e_shaded,
e_none,
e_wireframe,
e_wireframe_shaded,
e_first_render_mode = e_shaded,
e_last_render_mode = e_wireframe_shaded
};
class BSP_MeshDrawer
{
public :
static
void
DrawMesh(
BSP_TMesh &mesh,
int render_mode
);
private :
static
void
DrawPolies(
BSP_TMesh &mesh
);
BSP_MeshDrawer(
);
~BSP_MeshDrawer(
);
};
#endif

View File

@@ -1,192 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "BSP_PlyLoader.h"
#include "MT_Vector3.h"
#include "ply.h"
struct LoadVertex {
float x,y,z; /* the usual 3-space position of a vertex */
};
struct LoadFace {
unsigned char intensity; /* this user attaches intensity to faces */
unsigned char nverts; /* number of vertex indices in list */
int *verts; /* vertex index list */
};
MEM_SmartPtr<BSP_TMesh>
BSP_PlyLoader::
NewMeshFromFile(
char * file_name,
MT_Vector3 &min,
MT_Vector3 &max
) {
min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY);
max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY);
PlyProperty vert_props[] = { /* list of property information for a vertex */
{"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0},
{"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0},
{"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0},
};
PlyProperty face_props[] = { /* list of property information for a vertex */
{"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts),
1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)},
};
MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh;
if (mesh == NULL) return NULL;
int i,j;
PlyFile *ply;
int nelems;
char **elist;
int file_type;
float version;
int nprops;
int num_elems;
PlyProperty **plist;
char *elem_name;
LoadVertex load_vertex;
LoadFace load_face;
/* open a PLY file for reading */
ply = ply_open_for_reading(
file_name,
&nelems,
&elist,
&file_type,
&version
);
if (ply == NULL) return NULL;
/* go through each kind of element that we learned is in the file */
/* and read them */
for (i = 0; i < nelems; i++) {
/* get the description of the first element */
elem_name = elist[i];
plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
/* print the name of the element, for debugging */
/* if we're on vertex elements, read them in */
if (equal_strings ("vertex", elem_name)) {
/* set up for getting vertex elements */
ply_get_property (ply, elem_name, &vert_props[0]);
ply_get_property (ply, elem_name, &vert_props[1]);
ply_get_property (ply, elem_name, &vert_props[2]);
// make some memory for the vertices
mesh->VertexSet().reserve(num_elems);
/* grab all the vertex elements */
for (j = 0; j < num_elems; j++) {
/* grab and element from the file */
ply_get_element (ply, (void *)&load_vertex);
// pass the vertex into the mesh builder.
if (load_vertex.x < min.x()) {
min.x() = load_vertex.x;
} else
if (load_vertex.x > max.x()) {
max.x()= load_vertex.x;
}
if (load_vertex.y < min.y()) {
min.y() = load_vertex.y;
} else
if (load_vertex.y > max.y()) {
max.y()= load_vertex.y;
}
if (load_vertex.z < min.z()) {
min.z() = load_vertex.z;
} else
if (load_vertex.z > max.z()) {
max.z()= load_vertex.z;
}
BSP_TVertex my_vert;
my_vert.m_pos = MT_Vector3(load_vertex.x,load_vertex.y,load_vertex.z);
mesh->VertexSet().push_back(my_vert);
}
}
/* if we're on face elements, read them in */
if (equal_strings ("face", elem_name)) {
/* set up for getting face elements */
ply_get_property (ply, elem_name, &face_props[0]);
/* grab all the face elements */
for (j = 0; j < num_elems; j++) {
ply_get_element (ply, (void *)&load_face);
int v;
for (v = 2; v< load_face.nverts; v++) {
BSP_TFace f;
f.m_verts[0] = load_face.verts[0];
f.m_verts[1] = load_face.verts[v-1];
f.m_verts[2] = load_face.verts[v];
mesh->BuildNormal(f);
mesh->FaceSet().push_back(f);
}
// free up the memory this pile of shit used to allocate the polygon's vertices
free (load_face.verts);
}
}
}
/* close the PLY file */
ply_close (ply);
return mesh;
}

View File

@@ -1,60 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BSP_PLYLOADER_H__
#define __BSP_PLYLOADER_H__
#include "MEM_SmartPtr.h"
#include "BSP_TMesh.h"
class BSP_PlyLoader {
public :
static
MEM_SmartPtr<BSP_TMesh>
NewMeshFromFile(
char * file_name,
MT_Vector3 &min,
MT_Vector3 &max
);
private :
// unimplemented - not for instantiation.
BSP_PlyLoader(
);
~BSP_PlyLoader(
);
};
#endif

View File

@@ -1,397 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BSP_TMESH_H__
#define __BSP_TMESH_H__
#include "MT_Point3.h"
#include "MT_Vector3.h"
#include "MT_Transform.h"
#include "MEM_SmartPtr.h"
#include <vector>
#include "CSG_BooleanOps.h"
/**
* A very basic test mesh.
*/
struct BSP_TVertex {
MT_Point3 m_pos;
};
struct BSP_TFace {
int m_verts[3];
MT_Vector3 m_normal;
};
class BSP_TMesh {
public :
std::vector<BSP_TVertex> m_verts;
std::vector<BSP_TFace> m_faces;
MT_Vector3 m_min,m_max;
std::vector<BSP_TVertex> &
VertexSet(
){
return m_verts;
}
std::vector<BSP_TFace> &
FaceSet(
) {
return m_faces;
}
void
AddFace(
int *verts,
int num_verts
){
int i;
for (i= 2; i <num_verts; i++) {
BSP_TFace f;
f.m_verts[0] = verts[0];
f.m_verts[1] = verts[i-1];
f.m_verts[2] = verts[i];
m_faces.push_back(f);
BuildNormal(m_faces.back());
}
}
void
BuildNormal(
BSP_TFace & f
) const {
MT_Vector3 l1 =
m_verts[f.m_verts[1]].m_pos -
m_verts[f.m_verts[0]].m_pos;
MT_Vector3 l2 =
m_verts[f.m_verts[2]].m_pos -
m_verts[f.m_verts[1]].m_pos;
MT_Vector3 normal = l1.cross(l2);
f.m_normal = normal.safe_normalized();
}
};
/**
* some iterator functions to describe the mesh to the BSP module.
*/
/**
* This class defines 2 C style iterators over a CSG mesh, one for
* vertices and 1 for faces. They conform to the iterator interface
* defined in CSG_BooleanOps.h
*/
struct VertexIt {
BSP_TMesh * mesh;
BSP_TVertex * pos;
MT_Transform trans;
};
static
void
VertexIt_Destruct(
CSG_VertexIteratorDescriptor * iterator
) {
delete ((VertexIt *)(iterator->it));
iterator->it = NULL;
delete(iterator);
};
static
int
VertexIt_Done(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
if (vertex_it->pos < vertex_it->mesh->VertexSet().end()) return 0;
return 1;
};
static
void
VertexIt_Fill(
CSG_IteratorPtr it,
CSG_IVertex *vert
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
MT_Point3 p = vertex_it->pos->m_pos;
p = vertex_it->trans * p;
p.getValue(vert->position);
};
static
void
VertexIt_Step(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
++(vertex_it->pos);
};
static
void
VertexIt_Reset(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
VertexIt * vertex_it = (VertexIt *)it;
vertex_it->pos = vertex_it->mesh->VertexSet().begin();
};
static
CSG_VertexIteratorDescriptor *
VertexIt_Construct(
BSP_TMesh *mesh,
MT_Transform trans
){
// user should have insured mesh is not equal to NULL.
CSG_VertexIteratorDescriptor * output = new CSG_VertexIteratorDescriptor;
if (output == NULL) return NULL;
output->Done = VertexIt_Done;
output->Fill = VertexIt_Fill;
output->Step = VertexIt_Step;
output->Reset = VertexIt_Reset;
output->num_elements = mesh->VertexSet().size();
VertexIt * v_it = new VertexIt;
v_it->mesh = mesh;
v_it->pos = mesh->VertexSet().begin();
v_it->trans = trans;
output->it = v_it;
return output;
};
/**
* Face iterator.
*/
struct FaceIt {
BSP_TMesh * mesh;
BSP_TFace *pos;
};
static
void
FaceIt_Destruct(
CSG_FaceIteratorDescriptor * iterator
) {
delete ((FaceIt *)(iterator->it));
iterator->it = NULL;
delete(iterator);
};
static
int
FaceIt_Done(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
if (face_it->pos < face_it->mesh->FaceSet().end()) {
return 0;
}
return 1;
};
static
void
FaceIt_Fill(
CSG_IteratorPtr it,
CSG_IFace *face
){
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
// essentially iterating through a triangle fan here.
face->vertex_index[0] = int(face_it->pos->m_verts[0]);
face->vertex_index[1] = int(face_it->pos->m_verts[1]);
face->vertex_index[2] = int(face_it->pos->m_verts[2]);
face->vertex_number = 3;
};
static
void
FaceIt_Step(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
face_it->pos ++;
};
static
void
FaceIt_Reset(
CSG_IteratorPtr it
) {
// assume CSG_IteratorPtr is of the correct type.
FaceIt * face_it = (FaceIt *)it;
face_it->pos = face_it->mesh->FaceSet().begin();
};
static
CSG_FaceIteratorDescriptor *
FaceIt_Construct(
BSP_TMesh * mesh
) {
CSG_FaceIteratorDescriptor * output = new CSG_FaceIteratorDescriptor;
if (output == NULL) return NULL;
output->Done = FaceIt_Done;
output->Fill = FaceIt_Fill;
output->Step = FaceIt_Step;
output->Reset = FaceIt_Reset;
output->num_elements = mesh->FaceSet().size();
FaceIt * f_it = new FaceIt;
f_it->mesh = mesh;
f_it->pos = mesh->FaceSet().begin();
output->it = f_it;
return output;
};
/**
* Some Build functions.
*/
static
MEM_SmartPtr<BSP_TMesh>
BuildMesh(
CSG_MeshPropertyDescriptor &props,
CSG_FaceIteratorDescriptor &face_it,
CSG_VertexIteratorDescriptor &vertex_it
) {
MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh();
CSG_IVertex vert;
while (!vertex_it.Done(vertex_it.it)) {
vertex_it.Fill(vertex_it.it,&vert);
BSP_TVertex v;
v.m_pos = MT_Point3(vert.position);
mesh->VertexSet().push_back(v);
vertex_it.Step(vertex_it.it);
}
CSG_IFace face;
while (!face_it.Done(face_it.it)) {
face_it.Fill(face_it.it,&face);
BSP_TFace f;
f.m_verts[0] = face.vertex_index[0],
f.m_verts[1] = face.vertex_index[1],
f.m_verts[2] = face.vertex_index[2],
mesh->BuildNormal(f);
mesh->FaceSet().push_back(f);
face_it.Step(face_it.it);
}
return mesh;
};
#endif

View File

@@ -1,143 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "BSP_GhostTest3D.h"
#include "BSP_TMesh.h"
#include "MEM_SmartPtr.h"
#include "BSP_PlyLoader.h"
#include <iostream>
using namespace std;
#if 1
MEM_SmartPtr<BSP_TMesh>
NewTestMesh(
int x,
int y,
MT_Scalar fx,
MT_Scalar fy,
MT_Scalar ampx,
MT_Scalar ampy,
MT_Scalar sx,
MT_Scalar sy
) {
MEM_SmartPtr<BSP_TMesh> output = new BSP_TMesh;
std::vector<BSP_TVertex> &verts = output->VertexSet();
int i,j;
MT_Scalar x_scale = fx*MT_PI/x;
MT_Scalar y_scale = fy*MT_PI/y;
MT_Scalar fsx = sx/x;
MT_Scalar fsy = sy/y;
for (j = 0; j < y; j++) {
for (i = 0; i < x; i++) {
float z = ampx*sin(x_scale * i) + ampy*sin(y_scale * j);
MT_Vector3 val(i*fsx - sx/2,j*fsy - sy/2,z);
BSP_TVertex chuff;
chuff.m_pos = val;
verts.push_back(chuff);
}
}
int poly[4];
for (j = 0; j < (y-1); j++) {
for (i = 0; i < (x-1); i++) {
poly[0] = j*x + i;
poly[1] = poly[0] + 1;
poly[2] = poly[1] + y;
poly[3] = poly[2] -1;
output->AddFace(poly,4);
}
}
output->m_min = MT_Vector3(-sx/2,-sy/2,-ampx -ampy);
output->m_max = MT_Vector3(sx/2,sy/2,ampx + ampy);
return output;
}
#endif
int main()
{
MT_Vector3 min,max;
MT_Vector3 min2,max2;
#if 1
MEM_SmartPtr<BSP_TMesh> mesh1 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min,max);
MEM_SmartPtr<BSP_TMesh> mesh2 = BSP_PlyLoader::NewMeshFromFile("bsp_cube.ply",min2,max2);
mesh1->m_min = min;
mesh1->m_max = max;
mesh2->m_min = min2;
mesh1->m_max = max2;
#else
MEM_SmartPtr<BSP_TMesh> mesh1 = NewTestMesh(10,10,2,2,4,4,20,20);
MEM_SmartPtr<BSP_TMesh> mesh2 = NewTestMesh(10,10,2,2,4,4,20,20);
#endif
if (!mesh1) {
cout << "could not load mesh!";
return 0;
}
// MEM_SmartPtr<BSP_TMesh> mesh2 = new BSP_TMesh(mesh1.Ref());
BSP_GhostTestApp3D app;
cout << "Mesh polygons :" << mesh1->FaceSet().size() << "\n";
cout << "Mesh vertices :" << mesh1->VertexSet().size() << "\n";
app.SetMesh(mesh1);
app.SetMesh(mesh2);
app.InitApp();
app.Run();
return 0;
}

View File

@@ -1,196 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/*
Header for PLY polygon files.
- Greg Turk, March 1994
A PLY file contains a single polygonal _object_.
An object is composed of lists of _elements_. Typical elements are
vertices, faces, edges and materials.
Each type of element for a given object has one or more _properties_
associated with the element type. For instance, a vertex element may
have as properties three floating-point values x,y,z and three unsigned
chars for red, green and blue.
---------------------------------------------------------------
Copyright (c) 1994 The Board of Trustees of The Leland Stanford
Junior University. All rights reserved.
Permission to use, copy, modify and distribute this software and its
documentation for any purpose is hereby granted without fee, provided
that the above copyright notice and this permission notice appear in
all copies of this software and that you do not sell the software.
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __PLY_H__
#define __PLY_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stddef.h>
#define PLY_ASCII 1 /* ascii PLY file */
#define PLY_BINARY_BE 2 /* binary PLY file, big endian */
#define PLY_BINARY_LE 3 /* binary PLY file, little endian */
#define PLY_OKAY 0 /* ply routine worked okay */
#define PLY_ERROR -1 /* error in ply routine */
/* scalar data types supported by PLY format */
#define PLY_START_TYPE 0
#define PLY_CHAR 1
#define PLY_SHORT 2
#define PLY_INT 3
#define PLY_UCHAR 4
#define PLY_USHORT 5
#define PLY_UINT 6
#define PLY_FLOAT 7
#define PLY_DOUBLE 8
#define PLY_END_TYPE 9
#define PLY_SCALAR 0
#define PLY_LIST 1
typedef struct PlyProperty { /* description of a property */
char *name; /* property name */
int external_type; /* file's data type */
int internal_type; /* program's data type */
int offset; /* offset bytes of prop in a struct */
int is_list; /* 1 = list, 0 = scalar */
int count_external; /* file's count type */
int count_internal; /* program's count type */
int count_offset; /* offset byte for list count */
} PlyProperty;
typedef struct PlyElement { /* description of an element */
char *name; /* element name */
int num; /* number of elements in this object */
int size; /* size of element (bytes) or -1 if variable */
int nprops; /* number of properties for this element */
PlyProperty **props; /* list of properties in the file */
char *store_prop; /* flags: property wanted by user? */
int other_offset; /* offset to un-asked-for props, or -1 if none*/
int other_size; /* size of other_props structure */
} PlyElement;
typedef struct PlyOtherProp { /* describes other properties in an element */
char *name; /* element name */
int size; /* size of other_props */
int nprops; /* number of properties in other_props */
PlyProperty **props; /* list of properties in other_props */
} PlyOtherProp;
typedef struct OtherData { /* for storing other_props for an other element */
void *other_props;
} OtherData;
typedef struct OtherElem { /* data for one "other" element */
char *elem_name; /* names of other elements */
int elem_count; /* count of instances of each element */
OtherData **other_data; /* actual property data for the elements */
PlyOtherProp *other_props; /* description of the property data */
} OtherElem;
typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */
int num_elems; /* number of other elements */
OtherElem *other_list; /* list of data for other elements */
} PlyOtherElems;
typedef struct PlyFile { /* description of PLY file */
FILE *fp; /* file pointer */
int file_type; /* ascii or binary */
float version; /* version number of file */
int nelems; /* number of elements of object */
PlyElement **elems; /* list of elements */
int num_comments; /* number of comments */
char **comments; /* list of comments */
int num_obj_info; /* number of items of object information */
char **obj_info; /* list of object info items */
PlyElement *which_elem; /* which element we're currently writing */
PlyOtherElems *other_elems; /* "other" elements from a PLY file */
} PlyFile;
/* memory allocation */
static char *my_alloc();
#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
/*** delcaration of routines ***/
extern PlyFile *ply_write(FILE *, int, char **, int);
extern PlyFile *ply_open_for_writing(char *, int, char **, int, float *);
extern void ply_describe_element(PlyFile *, char *, int, int, PlyProperty *);
extern void ply_describe_property(PlyFile *, char *, PlyProperty *);
extern void ply_element_count(PlyFile *, char *, int);
extern void ply_header_complete(PlyFile *);
extern void ply_put_element_setup(PlyFile *, char *);
extern void ply_put_element(PlyFile *, void *);
extern void ply_put_comment(PlyFile *, char *);
extern void ply_put_obj_info(PlyFile *, char *);
extern PlyFile *ply_read(FILE *, int *, char ***);
extern PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *);
extern PlyProperty **ply_get_element_description(PlyFile *, char *, int*, int*);
extern void ply_get_element_setup( PlyFile *, char *, int, PlyProperty *);
extern void ply_get_property(PlyFile *, char *, PlyProperty *);
extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int);
extern void ply_get_element(PlyFile *, void *);
extern char **ply_get_comments(PlyFile *, int *);
extern char **ply_get_obj_info(PlyFile *, int *);
extern void ply_close(PlyFile *);
extern void ply_get_info(PlyFile *, float *, int *);
extern PlyOtherElems *ply_get_other_element (PlyFile *, char *, int);
extern void ply_describe_other_elements ( PlyFile *, PlyOtherElems *);
extern void ply_put_other_elements (PlyFile *);
extern void ply_free_other_elements (PlyOtherElems *);
extern int equal_strings(char *, char *);
#ifdef __cplusplus
}
#endif
#endif /* !__PLY_H__ */

View File

@@ -1,2545 +0,0 @@
/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/*
The interface routines for reading and writing PLY polygon files.
Greg Turk, February 1994
---------------------------------------------------------------
A PLY file contains a single polygonal _object_.
An object is composed of lists of _elements_. Typical elements are
vertices, faces, edges and materials.
Each type of element for a given object has one or more _properties_
associated with the element type. For instance, a vertex element may
have as properties the floating-point values x,y,z and the three unsigned
chars representing red, green and blue.
---------------------------------------------------------------
Copyright (c) 1994 The Board of Trustees of The Leland Stanford
Junior University. All rights reserved.
Permission to use, copy, modify and distribute this software and its
documentation for any purpose is hereby granted without fee, provided
that the above copyright notice and this permission notice appear in
all copies of this software and that you do not sell the software.
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "ply.h"
char *type_names[] = {
"invalid",
"char", "short", "int",
"uchar", "ushort", "uint",
"float", "double",
};
int ply_type_size[] = {
0, 1, 2, 4, 1, 2, 4, 4, 8
};
#define NO_OTHER_PROPS -1
#define DONT_STORE_PROP 0
#define STORE_PROP 1
#define OTHER_PROP 0
#define NAMED_PROP 1
/* returns 1 if strings are equal, 0 if not */
int equal_strings(char *, char *);
/* find an element in a plyfile's list */
PlyElement *find_element(PlyFile *, char *);
/* find a property in an element's list */
PlyProperty *find_property(PlyElement *, char *, int *);
/* write to a file the word describing a PLY file data type */
void write_scalar_type(FILE *, int);
/* read a line from a file and break it up into separate words */
char **get_words(FILE *, int *, char **);
char **old_get_words(FILE *, int *);
/* write an item to a file */
void write_binary_item(FILE *, int, unsigned int, double, int);
void write_ascii_item(FILE *, int, unsigned int, double, int);
double old_write_ascii_item(FILE *, char *, int);
/* add information to a PLY file descriptor */
void add_element(PlyFile *, char **);
void add_property(PlyFile *, char **);
void add_comment(PlyFile *, char *);
void add_obj_info(PlyFile *, char *);
/* copy a property */
void copy_property(PlyProperty *, PlyProperty *);
/* store a value into where a pointer and a type specify */
void store_item(char *, int, int, unsigned int, double);
/* return the value of a stored item */
void get_stored_item(void *, int, int *, unsigned int *, double *);
/* return the value stored in an item, given ptr to it and its type */
double get_item_value(char *, int);
/* get binary or ascii item and store it according to ptr and type */
void get_ascii_item(char *, int, int *, unsigned int *, double *);
void get_binary_item(FILE *, int, int *, unsigned int *, double *);
/* get a bunch of elements from a file */
void ascii_get_element(PlyFile *, char *);
void binary_get_element(PlyFile *, char *);
/* memory allocation */
char *my_alloc(int, int, char *);
/*************/
/* Writing */
/*************/
/******************************************************************************
Given a file pointer, get ready to write PLY data to the file.
Entry:
fp - the given file pointer
nelems - number of elements in object
elem_names - list of element names
file_type - file type, either ascii or binary
Exit:
returns a pointer to a PlyFile, used to refer to this file, or NULL if error
******************************************************************************/
PlyFile *ply_write(
FILE *fp,
int nelems,
char **elem_names,
int file_type
)
{
int i;
PlyFile *plyfile;
PlyElement *elem;
/* check for NULL file pointer */
if (fp == NULL)
return (NULL);
/* create a record for this object */
plyfile = (PlyFile *) myalloc(sizeof(PlyFile));
plyfile->file_type = file_type;
plyfile->num_comments = 0;
plyfile->num_obj_info = 0;
plyfile->nelems = nelems;
plyfile->version = 1.0;
plyfile->fp = fp;
plyfile->other_elems = NULL;
/* tuck aside the names of the elements */
plyfile->elems = (PlyElement **) myalloc(sizeof(PlyElement *) * nelems);
for (i = 0; i < nelems; i++) {
elem = (PlyElement *) myalloc(sizeof(PlyElement));
plyfile->elems[i] = elem;
elem->name = strdup(elem_names[i]);
elem->num = 0;
elem->nprops = 0;
}
/* return pointer to the file descriptor */
return (plyfile);
}
/******************************************************************************
Open a polygon file for writing.
Entry:
filename - name of file to read from
nelems - number of elements in object
elem_names - list of element names
file_type - file type, either ascii or binary
Exit:
version - version number of PLY file
returns a file identifier, used to refer to this file, or NULL if error
******************************************************************************/
PlyFile *ply_open_for_writing(
char *filename,
int nelems,
char **elem_names,
int file_type,
float *version
)
{
PlyFile *plyfile;
char *name;
FILE *fp;
/* tack on the extension .ply, if necessary */
name = (char *) myalloc(sizeof(char) * (strlen(filename) + 5));
strcpy(name, filename);
if (strlen(name) < 4 ||
strcmp(name + strlen(name) - 4, ".ply") != 0)
strcat(name, ".ply");
/* open the file for writing */
fp = fopen(name, "w");
if (fp == NULL) {
return (NULL);
}
/* create the actual PlyFile structure */
plyfile = ply_write(fp, nelems, elem_names, file_type);
if (plyfile == NULL)
return (NULL);
/* say what PLY file version number we're writing */
*version = plyfile->version;
/* return pointer to the file descriptor */
return (plyfile);
}
/******************************************************************************
Describe an element, including its properties and how many will be written
to the file.
Entry:
plyfile - file identifier
elem_name - name of element that information is being specified about
nelems - number of elements of this type to be written
nprops - number of properties contained in the element
prop_list - list of properties
******************************************************************************/
void ply_describe_element(
PlyFile *plyfile,
char *elem_name,
int nelems,
int nprops,
PlyProperty *prop_list
)
{
int i;
PlyElement *elem;
PlyProperty *prop;
/* look for appropriate element */
elem = find_element(plyfile, elem_name);
if (elem == NULL) {
fprintf(stderr, "ply_describe_element: can't find element '%s'\n", elem_name);
exit(-1);
}
elem->num = nelems;
/* copy the list of properties */
elem->nprops = nprops;
elem->props = (PlyProperty **) myalloc(sizeof(PlyProperty *) * nprops);
elem->store_prop = (char *) myalloc(sizeof(char) * nprops);
for (i = 0; i < nprops; i++) {
prop = (PlyProperty *) myalloc(sizeof(PlyProperty));
elem->props[i] = prop;
elem->store_prop[i] = NAMED_PROP;
copy_property(prop, &prop_list[i]);
}
}
/******************************************************************************
Describe a property of an element.
Entry:
plyfile - file identifier
elem_name - name of element that information is being specified about
prop - the new property
******************************************************************************/
void ply_describe_property(
PlyFile *plyfile,
char *elem_name,
PlyProperty *prop
)
{
PlyElement *elem;
PlyProperty *elem_prop;
/* look for appropriate element */
elem = find_element(plyfile, elem_name);
if (elem == NULL) {
fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
elem_name);
return;
}
/* create room for new property */
if (elem->nprops == 0) {
elem->props = (PlyProperty **) myalloc(sizeof(PlyProperty *));
elem->store_prop = (char *) myalloc(sizeof(char));
elem->nprops = 1;
}
else {
elem->nprops++;
elem->props = (PlyProperty **)
realloc(elem->props, sizeof(PlyProperty *) * elem->nprops);
elem->store_prop = (char *)
realloc(elem->store_prop, sizeof(char) * elem->nprops);
}
/* copy the new property */
elem_prop = (PlyProperty *) myalloc(sizeof(PlyProperty));
elem->props[elem->nprops - 1] = elem_prop;
elem->store_prop[elem->nprops - 1] = NAMED_PROP;
copy_property(elem_prop, prop);
}
/******************************************************************************
Describe what the "other" properties are that are to be stored, and where
they are in an element.
******************************************************************************/
void ply_describe_other_properties(
PlyFile *plyfile,
PlyOtherProp *other,
int offset
)
{
int i;
PlyElement *elem;
PlyProperty *prop;
/* look for appropriate element */
elem = find_element(plyfile, other->name);
if (elem == NULL) {
fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
other->name);
return;
}
/* create room for other properties */
if (elem->nprops == 0) {
elem->props = (PlyProperty **)
myalloc(sizeof(PlyProperty *) * other->nprops);
elem->store_prop = (char *) myalloc(sizeof(char) * other->nprops);
elem->nprops = 0;
}
else {
int newsize;
newsize = elem->nprops + other->nprops;
elem->props = (PlyProperty **)
realloc(elem->props, sizeof(PlyProperty *) * newsize);
elem->store_prop = (char *)
realloc(elem->store_prop, sizeof(char) * newsize);
}
/* copy the other properties */
for (i = 0; i < other->nprops; i++) {
prop = (PlyProperty *) myalloc(sizeof(PlyProperty));
copy_property(prop, other->props[i]);
elem->props[elem->nprops] = prop;
elem->store_prop[elem->nprops] = OTHER_PROP;
elem->nprops++;
}
/* save other info about other properties */
elem->other_size = other->size;
elem->other_offset = offset;
}
/******************************************************************************
State how many of a given element will be written.
Entry:
plyfile - file identifier
elem_name - name of element that information is being specified about
nelems - number of elements of this type to be written
******************************************************************************/
void ply_element_count(
PlyFile *plyfile,
char *elem_name,
int nelems
)
{
PlyElement *elem;
/* look for appropriate element */
elem = find_element(plyfile, elem_name);
if (elem == NULL) {
fprintf(stderr, "ply_element_count: can't find element '%s'\n", elem_name);
exit(-1);
}
elem->num = nelems;
}
/******************************************************************************
Signal that we've described everything a PLY file's header and that the
header should be written to the file.
Entry:
plyfile - file identifier
******************************************************************************/
void ply_header_complete(PlyFile *plyfile)
{
int i, j;
FILE *fp = plyfile->fp;
PlyElement *elem;
PlyProperty *prop;
fprintf(fp, "ply\n");
switch (plyfile->file_type) {
case PLY_ASCII:
fprintf(fp, "format ascii 1.0\n");
break;
case PLY_BINARY_BE:
fprintf(fp, "format binary_big_endian 1.0\n");
break;
case PLY_BINARY_LE:
fprintf(fp, "format binary_little_endian 1.0\n");
break;
default:
fprintf(stderr, "ply_header_complete: bad file type = %d\n",
plyfile->file_type);
exit(-1);
}
/* write out the comments */
for (i = 0; i < plyfile->num_comments; i++)
fprintf(fp, "comment %s\n", plyfile->comments[i]);
/* write out object information */
for (i = 0; i < plyfile->num_obj_info; i++)
fprintf(fp, "obj_info %s\n", plyfile->obj_info[i]);
/* write out information about each element */
for (i = 0; i < plyfile->nelems; i++) {
elem = plyfile->elems[i];
fprintf(fp, "element %s %d\n", elem->name, elem->num);
/* write out each property */
for (j = 0; j < elem->nprops; j++) {
prop = elem->props[j];
if (prop->is_list) {
fprintf(fp, "property list ");
write_scalar_type(fp, prop->count_external);
fprintf(fp, " ");
write_scalar_type(fp, prop->external_type);
fprintf(fp, " %s\n", prop->name);
}
else {
fprintf(fp, "property ");
write_scalar_type(fp, prop->external_type);
fprintf(fp, " %s\n", prop->name);
}
}
}
fprintf(fp, "end_header\n");
}
/******************************************************************************
Specify which elements are going to be written. This should be called
before a call to the routine ply_put_element().
Entry:
plyfile - file identifier
elem_name - name of element we're talking about
******************************************************************************/
void ply_put_element_setup(PlyFile *plyfile, char *elem_name)
{
PlyElement *elem;
elem = find_element(plyfile, elem_name);
if (elem == NULL) {
fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
exit(-1);
}
plyfile->which_elem = elem;
}
/******************************************************************************
Write an element to the file. This routine assumes that we're
writing the type of element specified in the last call to the routine
ply_put_element_setup().
Entry:
plyfile - file identifier
elem_ptr - pointer to the element
******************************************************************************/
void ply_put_element(PlyFile *plyfile, void *elem_ptr)
{
int j, k;
FILE *fp = plyfile->fp;
PlyElement *elem;
PlyProperty *prop;
char *elem_data, *item;
char **item_ptr;
int list_count;
int item_size;
int int_val;
unsigned int uint_val;
double double_val;
char **other_ptr;
elem = plyfile->which_elem;
elem_data = elem_ptr;
other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
/* write out either to an ascii or binary file */
if (plyfile->file_type == PLY_ASCII) {
/* write an ascii file */
/* write out each property of the element */
for (j = 0; j < elem->nprops; j++) {
prop = elem->props[j];
if (elem->store_prop[j] == OTHER_PROP)
elem_data = *other_ptr;
else
elem_data = elem_ptr;
if (prop->is_list) {
item = elem_data + prop->count_offset;
get_stored_item((void *) item, prop->count_internal,
&int_val, &uint_val, &double_val);
write_ascii_item(fp, int_val, uint_val, double_val,
prop->count_external);
list_count = uint_val;
item_ptr = (char **) (elem_data + prop->offset);
item = item_ptr[0];
item_size = ply_type_size[prop->internal_type];
for (k = 0; k < list_count; k++) {
get_stored_item((void *) item, prop->internal_type,
&int_val, &uint_val, &double_val);
write_ascii_item(fp, int_val, uint_val, double_val,
prop->external_type);
item += item_size;
}
}
else {
item = elem_data + prop->offset;
get_stored_item((void *) item, prop->internal_type,
&int_val, &uint_val, &double_val);
write_ascii_item(fp, int_val, uint_val, double_val,
prop->external_type);
}
}
fprintf(fp, "\n");
}
else {
/* write a binary file */
/* write out each property of the element */
for (j = 0; j < elem->nprops; j++) {
prop = elem->props[j];
if (elem->store_prop[j] == OTHER_PROP)
elem_data = *other_ptr;
else
elem_data = elem_ptr;
if (prop->is_list) {
item = elem_data + prop->count_offset;
item_size = ply_type_size[prop->count_internal];
get_stored_item((void *) item, prop->count_internal,
&int_val, &uint_val, &double_val);
write_binary_item(fp, int_val, uint_val, double_val,
prop->count_external);
list_count = uint_val;
item_ptr = (char **) (elem_data + prop->offset);
item = item_ptr[0];
item_size = ply_type_size[prop->internal_type];
for (k = 0; k < list_count; k++) {
get_stored_item((void *) item, prop->internal_type,
&int_val, &uint_val, &double_val);
write_binary_item(fp, int_val, uint_val, double_val,
prop->external_type);
item += item_size;
}
}
else {
item = elem_data + prop->offset;
item_size = ply_type_size[prop->internal_type];
get_stored_item((void *) item, prop->internal_type,
&int_val, &uint_val, &double_val);
write_binary_item(fp, int_val, uint_val, double_val,
prop->external_type);
}
}
}
}
/******************************************************************************
Specify a comment that will be written in the header.
Entry:
plyfile - file identifier
comment - the comment to be written
******************************************************************************/
void ply_put_comment(PlyFile *plyfile, char *comment)
{
/* (re)allocate space for new comment */
if (plyfile->num_comments == 0)
plyfile->comments = (char **) myalloc(sizeof(char *));
else
plyfile->comments = (char **) realloc(plyfile->comments,
sizeof(char *) * (plyfile->num_comments + 1));
/* add comment to list */
plyfile->comments[plyfile->num_comments] = strdup(comment);
plyfile->num_comments++;
}
/******************************************************************************
Specify a piece of object information (arbitrary text) that will be written
in the header.
Entry:
plyfile - file identifier
obj_info - the text information to be written
******************************************************************************/
void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
{
/* (re)allocate space for new info */
if (plyfile->num_obj_info == 0)
plyfile->obj_info = (char **) myalloc(sizeof(char *));
else
plyfile->obj_info = (char **) realloc(plyfile->obj_info,
sizeof(char *) * (plyfile->num_obj_info + 1));
/* add info to list */
plyfile->obj_info[plyfile->num_obj_info] = strdup(obj_info);
plyfile->num_obj_info++;
}
/*************/
/* Reading */
/*************/
/******************************************************************************
Given a file pointer, get ready to read PLY data from the file.
Entry:
fp - the given file pointer
Exit:
nelems - number of elements in object
elem_names - list of element names
returns a pointer to a PlyFile, used to refer to this file, or NULL if error
******************************************************************************/
PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
{
int i, j;
PlyFile *plyfile;
int nwords;
char **words;
int found_format = 0;
char **elist;
PlyElement *elem;
char *orig_line;
/* check for NULL file pointer */
if (fp == NULL)
return (NULL);
/* create record for this object */
plyfile = (PlyFile *) myalloc(sizeof(PlyFile));
plyfile->nelems = 0;
plyfile->comments = NULL;
plyfile->num_comments = 0;
plyfile->obj_info = NULL;
plyfile->num_obj_info = 0;
plyfile->fp = fp;
plyfile->other_elems = NULL;
/* read and parse the file's header */
words = get_words(plyfile->fp, &nwords, &orig_line);
if (!words || !equal_strings(words[0], "ply"))
return (NULL);
while (words) {
/* parse words */
if (equal_strings(words[0], "format")) {
if (nwords != 3)
return (NULL);
if (equal_strings(words[1], "ascii"))
plyfile->file_type = PLY_ASCII;
else if (equal_strings(words[1], "binary_big_endian"))
plyfile->file_type = PLY_BINARY_BE;
else if (equal_strings(words[1], "binary_little_endian"))
plyfile->file_type = PLY_BINARY_LE;
else
return (NULL);
plyfile->version = (float)atof(words[2]);
found_format = 1;
}
else if (equal_strings(words[0], "element"))
add_element(plyfile, words);
else if (equal_strings(words[0], "property"))
add_property(plyfile, words);
else if (equal_strings(words[0], "comment"))
add_comment(plyfile, orig_line);
else if (equal_strings(words[0], "obj_info"))
add_obj_info(plyfile, orig_line);
else if (equal_strings(words[0], "end_header"))
break;
/* free up words space */
free(words);
words = get_words(plyfile->fp, &nwords, &orig_line);
}
/* create tags for each property of each element, to be used */
/* later to say whether or not to store each property for the user */
for (i = 0; i < plyfile->nelems; i++) {
elem = plyfile->elems[i];
elem->store_prop = (char *) myalloc(sizeof(char) * elem->nprops);
for (j = 0; j < elem->nprops; j++)
elem->store_prop[j] = DONT_STORE_PROP;
elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
}
/* set return values about the elements */
elist = (char **) myalloc(sizeof(char *) * plyfile->nelems);
for (i = 0; i < plyfile->nelems; i++)
elist[i] = strdup(plyfile->elems[i]->name);
*elem_names = elist;
*nelems = plyfile->nelems;
/* return a pointer to the file's information */
return (plyfile);
}
/******************************************************************************
Open a polygon file for reading.
Entry:
filename - name of file to read from
Exit:
nelems - number of elements in object
elem_names - list of element names
file_type - file type, either ascii or binary
version - version number of PLY file
returns a file identifier, used to refer to this file, or NULL if error
******************************************************************************/
PlyFile *ply_open_for_reading(
char *filename,
int *nelems,
char ***elem_names,
int *file_type,
float *version
)
{
FILE *fp;
PlyFile *plyfile;
char *name;
/* tack on the extension .ply, if necessary */
name = (char *) myalloc(sizeof(char) * (strlen(filename) + 5));
strcpy(name, filename);
if (strlen(name) < 4 ||
strcmp(name + strlen(name) - 4, ".ply") != 0)
strcat(name, ".ply");
/* open the file for reading */
fp = fopen(name, "r");
if (fp == NULL)
return (NULL);
/* create the PlyFile data structure */
plyfile = ply_read(fp, nelems, elem_names);
/* determine the file type and version */
*file_type = plyfile->file_type;
*version = plyfile->version;
/* return a pointer to the file's information */
return (plyfile);
}
/******************************************************************************
Get information about a particular element.
Entry:
plyfile - file identifier
elem_name - name of element to get information about
Exit:
nelems - number of elements of this type in the file
nprops - number of properties
returns a list of properties, or NULL if the file doesn't contain that elem
******************************************************************************/
PlyProperty **ply_get_element_description(
PlyFile *plyfile,
char *elem_name,
int *nelems,
int *nprops
)
{
int i;
PlyElement *elem;
PlyProperty *prop;
PlyProperty **prop_list;
/* find information about the element */
elem = find_element(plyfile, elem_name);
if (elem == NULL)
return (NULL);
*nelems = elem->num;
*nprops = elem->nprops;
/* make a copy of the element's property list */
prop_list = (PlyProperty **) myalloc(sizeof(PlyProperty *) * elem->nprops);
for (i = 0; i < elem->nprops; i++) {
prop = (PlyProperty *) myalloc(sizeof(PlyProperty));
copy_property(prop, elem->props[i]);
prop_list[i] = prop;
}
/* return this duplicate property list */
return (prop_list);
}
/******************************************************************************
Specify which properties of an element are to be returned. This should be
called before a call to the routine ply_get_element().
Entry:
plyfile - file identifier
elem_name - which element we're talking about
nprops - number of properties
prop_list - list of properties
******************************************************************************/
void ply_get_element_setup(
PlyFile *plyfile,
char *elem_name,
int nprops,
PlyProperty *prop_list
)
{
int i;
PlyElement *elem;
PlyProperty *prop;
int index;
/* find information about the element */
elem = find_element(plyfile, elem_name);
plyfile->which_elem = elem;
/* deposit the property information into the element's description */
for (i = 0; i < nprops; i++) {
/* look for actual property */
prop = find_property(elem, prop_list[i].name, &index);
if (prop == NULL) {
fprintf(stderr, "Warning: Can't find property '%s' in element '%s'\n",
prop_list[i].name, elem_name);
continue;
}
/* store its description */
prop->internal_type = prop_list[i].internal_type;
prop->offset = prop_list[i].offset;
prop->count_internal = prop_list[i].count_internal;
prop->count_offset = prop_list[i].count_offset;
/* specify that the user wants this property */
elem->store_prop[index] = STORE_PROP;
}
}
/******************************************************************************
Specify a property of an element that is to be returned. This should be
called (usually multiple times) before a call to the routine ply_get_element().
This routine should be used in preference to the less flexible old routine
called ply_get_element_setup().
Entry:
plyfile - file identifier
elem_name - which element we're talking about
prop - property to add to those that will be returned
******************************************************************************/
void ply_get_property(
PlyFile *plyfile,
char *elem_name,
PlyProperty *prop
)
{
PlyElement *elem;
PlyProperty *prop_ptr;
int index;
/* find information about the element */
elem = find_element(plyfile, elem_name);
plyfile->which_elem = elem;
/* deposit the property information into the element's description */
prop_ptr = find_property(elem, prop->name, &index);
if (prop_ptr == NULL) {
fprintf(stderr, "Warning: Can't find property '%s' in element '%s'\n",
prop->name, elem_name);
return;
}
prop_ptr->internal_type = prop->internal_type;
prop_ptr->offset = prop->offset;
prop_ptr->count_internal = prop->count_internal;
prop_ptr->count_offset = prop->count_offset;
/* specify that the user wants this property */
elem->store_prop[index] = STORE_PROP;
}
/******************************************************************************
Read one element from the file. This routine assumes that we're reading
the type of element specified in the last call to the routine
ply_get_element_setup().
Entry:
plyfile - file identifier
elem_ptr - pointer to location where the element information should be put
******************************************************************************/
void ply_get_element(PlyFile *plyfile, void *elem_ptr)
{
if (plyfile->file_type == PLY_ASCII)
ascii_get_element(plyfile, (char *) elem_ptr);
else
binary_get_element(plyfile, (char *) elem_ptr);
}
/******************************************************************************
Extract the comments from the header information of a PLY file.
Entry:
plyfile - file identifier
Exit:
num_comments - number of comments returned
returns a pointer to a list of comments
******************************************************************************/
char **ply_get_comments(PlyFile *plyfile, int *num_comments)
{
*num_comments = plyfile->num_comments;
return (plyfile->comments);
}
/******************************************************************************
Extract the object information (arbitrary text) from the header information
of a PLY file.
Entry:
plyfile - file identifier
Exit:
num_obj_info - number of lines of text information returned
returns a pointer to a list of object info lines
******************************************************************************/
char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
{
*num_obj_info = plyfile->num_obj_info;
return (plyfile->obj_info);
}
/******************************************************************************
Make ready for "other" properties of an element-- those properties that
the user has not explicitly asked for, but that are to be stashed away
in a special structure to be carried along with the element's other
information.
Entry:
plyfile - file identifier
elem - element for which we want to save away other properties
******************************************************************************/
void setup_other_props(PlyElement *elem)
{
int i;
PlyProperty *prop;
int size = 0;
int type_size;
/* Examine each property in decreasing order of size. */
/* We do this so that all data types will be aligned by */
/* word, half-word, or whatever within the structure. */
for (type_size = 8; type_size > 0; type_size /= 2) {
/* add up the space taken by each property, and save this information */
/* away in the property descriptor */
for (i = 0; i < elem->nprops; i++) {
/* don't bother with properties we've been asked to store explicitly */
if (elem->store_prop[i])
continue;
prop = elem->props[i];
/* internal types will be same as external */
prop->internal_type = prop->external_type;
prop->count_internal = prop->count_external;
/* check list case */
if (prop->is_list) {
/* pointer to list */
if (type_size == sizeof(void *)) {
prop->offset = size;
size += sizeof(void *); /* always use size of a pointer here */
}
/* count of number of list elements */
if (type_size == ply_type_size[prop->count_external]) {
prop->count_offset = size;
size += ply_type_size[prop->count_external];
}
}
/* not list */
else if (type_size == ply_type_size[prop->external_type]) {
prop->offset = size;
size += ply_type_size[prop->external_type];
}
}
}
/* save the size for the other_props structure */
elem->other_size = size;
}
/******************************************************************************
Specify that we want the "other" properties of an element to be tucked
away within the user's structure. The user needn't be concerned for how
these properties are stored.
Entry:
plyfile - file identifier
elem_name - name of element that we want to store other_props in
offset - offset to where other_props will be stored inside user's structure
Exit:
returns pointer to structure containing description of other_props
******************************************************************************/
PlyOtherProp *ply_get_other_properties(
PlyFile *plyfile,
char *elem_name,
int offset
)
{
int i;
PlyElement *elem;
PlyOtherProp *other;
PlyProperty *prop;
int nprops;
/* find information about the element */
elem = find_element(plyfile, elem_name);
if (elem == NULL) {
fprintf(stderr, "ply_get_other_properties: Can't find element '%s'\n",
elem_name);
return (NULL);
}
/* remember that this is the "current" element */
plyfile->which_elem = elem;
/* save the offset to where to store the other_props */
elem->other_offset = offset;
/* place the appropriate pointers, etc. in the element's property list */
setup_other_props(elem);
/* create structure for describing other_props */
other = (PlyOtherProp *) myalloc(sizeof(PlyOtherProp));
other->name = strdup(elem_name);
#if 0
if (elem->other_offset == NO_OTHER_PROPS) {
other->size = 0;
other->props = NULL;
other->nprops = 0;
return (other);
}
#endif
other->size = elem->other_size;
other->props = (PlyProperty **) myalloc(sizeof(PlyProperty) * elem->nprops);
/* save descriptions of each "other" property */
nprops = 0;
for (i = 0; i < elem->nprops; i++) {
if (elem->store_prop[i])
continue;
prop = (PlyProperty *) myalloc(sizeof(PlyProperty));
copy_property(prop, elem->props[i]);
other->props[nprops] = prop;
nprops++;
}
other->nprops = nprops;
#if 1
/* set other_offset pointer appropriately if there are NO other properties */
if (other->nprops == 0) {
elem->other_offset = NO_OTHER_PROPS;
}
#endif
/* return structure */
return (other);
}
/*************************/
/* Other Element Stuff */
/*************************/
/******************************************************************************
Grab all the data for an element that a user does not want to explicitly
read in.
Entry:
plyfile - pointer to file
elem_name - name of element whose data is to be read in
elem_count - number of instances of this element stored in the file
Exit:
returns pointer to ALL the "other" element data for this PLY file
******************************************************************************/
PlyOtherElems *ply_get_other_element(
PlyFile *plyfile,
char *elem_name,
int elem_count
)
{
int i;
PlyElement *elem;
PlyOtherElems *other_elems;
OtherElem *other;
/* look for appropriate element */
elem = find_element(plyfile, elem_name);
if (elem == NULL) {
fprintf(stderr,
"ply_get_other_element: can't find element '%s'\n", elem_name);
exit(-1);
}
/* create room for the new "other" element, initializing the */
/* other data structure if necessary */
if (plyfile->other_elems == NULL) {
plyfile->other_elems = (PlyOtherElems *) myalloc(sizeof(PlyOtherElems));
other_elems = plyfile->other_elems;
other_elems->other_list = (OtherElem *) myalloc(sizeof(OtherElem));
other = &(other_elems->other_list[0]);
other_elems->num_elems = 1;
}
else {
other_elems = plyfile->other_elems;
other_elems->other_list = (OtherElem *) realloc(other_elems->other_list,
sizeof(OtherElem) * other_elems->num_elems + 1);
other = &(other_elems->other_list[other_elems->num_elems]);
other_elems->num_elems++;
}
/* count of element instances in file */
other->elem_count = elem_count;
/* save name of element */
other->elem_name = strdup(elem_name);
/* create a list to hold all the current elements */
other->other_data = (OtherData **)
malloc(sizeof(OtherData *) * other->elem_count);
/* set up for getting elements */
other->other_props = ply_get_other_properties(plyfile, elem_name,
offsetof(OtherData, other_props));
/* grab all these elements */
for (i = 0; i < other->elem_count; i++) {
/* grab and element from the file */
other->other_data[i] = (OtherData *) malloc(sizeof(OtherData));
ply_get_element(plyfile, (void *) other->other_data[i]);
}
/* return pointer to the other elements data */
return (other_elems);
}
/******************************************************************************
Pass along a pointer to "other" elements that we want to save in a given
PLY file. These other elements were presumably read from another PLY file.
Entry:
plyfile - file pointer in which to store this other element info
other_elems - info about other elements that we want to store
******************************************************************************/
void ply_describe_other_elements(
PlyFile *plyfile,
PlyOtherElems *other_elems
)
{
int i;
OtherElem *other;
/* ignore this call if there is no other element */
if (other_elems == NULL)
return;
/* save pointer to this information */
plyfile->other_elems = other_elems;
/* describe the other properties of this element */
for (i = 0; i < other_elems->num_elems; i++) {
other = &(other_elems->other_list[i]);
ply_element_count(plyfile, other->elem_name, other->elem_count);
ply_describe_other_properties(plyfile, other->other_props,
offsetof(OtherData, other_props));
}
}
/******************************************************************************
Write out the "other" elements specified for this PLY file.
Entry:
plyfile - pointer to PLY file to write out other elements for
******************************************************************************/
void ply_put_other_elements(PlyFile *plyfile)
{
int i, j;
OtherElem *other;
/* make sure we have other elements to write */
if (plyfile->other_elems == NULL)
return;
/* write out the data for each "other" element */
for (i = 0; i < plyfile->other_elems->num_elems; i++) {
other = &(plyfile->other_elems->other_list[i]);
ply_put_element_setup(plyfile, other->elem_name);
/* write out each instance of the current element */
for (j = 0; j < other->elem_count; j++)
ply_put_element(plyfile, (void *) other->other_data[j]);
}
}
/******************************************************************************
Free up storage used by an "other" elements data structure.
Entry:
other_elems - data structure to free up
******************************************************************************/
/*******************/
/* Miscellaneous */
/*******************/
/******************************************************************************
Close a PLY file.
Entry:
plyfile - identifier of file to close
******************************************************************************/
void ply_close(PlyFile *plyfile)
{
fclose(plyfile->fp);
/* free up memory associated with the PLY file */
free(plyfile);
}
/******************************************************************************
Get version number and file type of a PlyFile.
Entry:
ply - pointer to PLY file
Exit:
version - version of the file
file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
******************************************************************************/
void ply_get_info(PlyFile *ply, float *version, int *file_type)
{
if (ply == NULL)
return;
*version = ply->version;
*file_type = ply->file_type;
}
/******************************************************************************
Compare two strings. Returns 1 if they are the same, 0 if not.
******************************************************************************/
int equal_strings(char *s1, char *s2)
{
while (*s1 && *s2)
if (*s1++ != *s2++)
return (0);
if (*s1 != *s2)
return (0);
else
return (1);
}
/******************************************************************************
Find an element from the element list of a given PLY object.
Entry:
plyfile - file id for PLY file
element - name of element we're looking for
Exit:
returns the element, or NULL if not found
******************************************************************************/
PlyElement *find_element(PlyFile *plyfile, char *element)
{
int i;
for (i = 0; i < plyfile->nelems; i++)
if (equal_strings(element, plyfile->elems[i]->name))
return (plyfile->elems[i]);
return (NULL);
}
/******************************************************************************
Find a property in the list of properties of a given element.
Entry:
elem - pointer to element in which we want to find the property
prop_name - name of property to find
Exit:
index - index to position in list
returns a pointer to the property, or NULL if not found
******************************************************************************/
PlyProperty *find_property(PlyElement *elem, char *prop_name, int *index)
{
int i;
for (i = 0; i < elem->nprops; i++)
if (equal_strings(prop_name, elem->props[i]->name)) {
*index = i;
return (elem->props[i]);
}
*index = -1;
return (NULL);
}
/******************************************************************************
Read an element from an ascii file.
Entry:
plyfile - file identifier
elem_ptr - pointer to element
******************************************************************************/
void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
{
int j, k;
PlyElement *elem;
PlyProperty *prop;
char **words;
int nwords;
int which_word;
char *elem_data, *item;
char *item_ptr;
int item_size;
int int_val;
unsigned int uint_val;
double double_val;
int list_count;
int store_it;
char **store_array;
char *orig_line;
char *other_data;
int other_flag;
other_flag = 0;
other_data = NULL;
item = NULL;
item_size = 0;
/* the kind of element we're reading currently */
elem = plyfile->which_elem;
/* do we need to setup for other_props? */
if (elem->other_offset != NO_OTHER_PROPS) {
char **ptr;
other_flag = 1;
/* make room for other_props */
other_data = (char *) myalloc(elem->other_size);
/* store pointer in user's structure to the other_props */
ptr = (char **) (elem_ptr + elem->other_offset);
*ptr = other_data;
}
else {
other_flag = 0;
other_data = NULL;
item = NULL;
item_size = 0;
}
/* read in the element */
words = get_words(plyfile->fp, &nwords, &orig_line);
if (words == NULL) {
fprintf(stderr, "ply_get_element: unexpected end of file\n");
exit(-1);
}
which_word = 0;
for (j = 0; j < elem->nprops; j++) {
prop = elem->props[j];
store_it = (elem->store_prop[j] | other_flag);
/* store either in the user's structure or in other_props */
if (elem->store_prop[j])
elem_data = elem_ptr;
else
elem_data = other_data;
if (prop->is_list) { /* a list */
/* get and store the number of items in the list */
get_ascii_item(words[which_word++], prop->count_external,
&int_val, &uint_val, &double_val);
if (store_it) {
item = elem_data + prop->count_offset;
store_item(item, prop->count_internal, int_val, uint_val, double_val);
}
/* allocate space for an array of items and store a ptr to the array */
list_count = int_val;
item_size = ply_type_size[prop->internal_type];
store_array = (char **) (elem_data + prop->offset);
if (list_count == 0) {
if (store_it)
*store_array = NULL;
}
else {
if (store_it) {
item_ptr = (char *) myalloc(sizeof(char) * item_size * list_count);
item = item_ptr;
*store_array = item_ptr;
}
/* read items and store them into the array */
for (k = 0; k < list_count; k++) {
get_ascii_item(words[which_word++], prop->external_type,
&int_val, &uint_val, &double_val);
if (store_it) {
store_item(item, prop->internal_type,
int_val, uint_val, double_val);
item += item_size;
}
}
}
}
else { /* not a list */
get_ascii_item(words[which_word++], prop->external_type,
&int_val, &uint_val, &double_val);
if (store_it) {
item = elem_data + prop->offset;
store_item(item, prop->internal_type, int_val, uint_val, double_val);
}
}
}
free(words);
}
/******************************************************************************
Read an element from a binary file.
Entry:
plyfile - file identifier
elem_ptr - pointer to an element
******************************************************************************/
void binary_get_element(PlyFile *plyfile, char *elem_ptr)
{
int j, k;
PlyElement *elem;
PlyProperty *prop;
FILE *fp = plyfile->fp;
char *elem_data, *item;
char *item_ptr;
int item_size;
int int_val;
unsigned int uint_val;
double double_val;
int list_count;
int store_it;
char **store_array;
char *other_data;
int other_flag;
other_flag = 0;
other_data = NULL;
item = NULL;
item_size = 0;
/* the kind of element we're reading currently */
elem = plyfile->which_elem;
/* do we need to setup for other_props? */
if (elem->other_offset != NO_OTHER_PROPS) {
char **ptr;
other_flag = 1;
/* make room for other_props */
other_data = (char *) myalloc(elem->other_size);
/* store pointer in user's structure to the other_props */
ptr = (char **) (elem_ptr + elem->other_offset);
*ptr = other_data;
}
else {
other_flag = 0;
other_data = NULL;
item = NULL;
item_size = 0;
}
/* read in a number of elements */
for (j = 0; j < elem->nprops; j++) {
prop = elem->props[j];
store_it = (elem->store_prop[j] | other_flag);
/* store either in the user's structure or in other_props */
if (elem->store_prop[j])
elem_data = elem_ptr;
else
elem_data = other_data;
if (prop->is_list) { /* a list */
/* get and store the number of items in the list */
get_binary_item(fp, prop->count_external,
&int_val, &uint_val, &double_val);
if (store_it) {
item = elem_data + prop->count_offset;
store_item(item, prop->count_internal, int_val, uint_val, double_val);
}
/* allocate space for an array of items and store a ptr to the array */
list_count = int_val;
/* The "if" was added by Afra Zomorodian 8/22/95
* so that zipper won't crash reading plies that have additional
* properties.
*/
if (store_it) {
item_size = ply_type_size[prop->internal_type];
}
store_array = (char **) (elem_data + prop->offset);
if (list_count == 0) {
if (store_it)
*store_array = NULL;
}
else {
if (store_it) {
item_ptr = (char *) myalloc(sizeof(char) * item_size * list_count);
item = item_ptr;
*store_array = item_ptr;
}
/* read items and store them into the array */
for (k = 0; k < list_count; k++) {
get_binary_item(fp, prop->external_type,
&int_val, &uint_val, &double_val);
if (store_it) {
store_item(item, prop->internal_type,
int_val, uint_val, double_val);
item += item_size;
}
}
}
}
else { /* not a list */
get_binary_item(fp, prop->external_type,
&int_val, &uint_val, &double_val);
if (store_it) {
item = elem_data + prop->offset;
store_item(item, prop->internal_type, int_val, uint_val, double_val);
}
}
}
}
/******************************************************************************
Write to a file the word that represents a PLY data type.
Entry:
fp - file pointer
code - code for type
******************************************************************************/
void write_scalar_type(FILE *fp, int code)
{
/* make sure this is a valid code */
if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
fprintf(stderr, "write_scalar_type: bad data code = %d\n", code);
exit(-1);
}
/* write the code to a file */
fprintf(fp, "%s", type_names[code]);
}
/******************************************************************************
Get a text line from a file and break it up into words.
IMPORTANT: The calling routine call "free" on the returned pointer once
finished with it.
Entry:
fp - file to read from
Exit:
nwords - number of words returned
orig_line - the original line of characters
returns a list of words from the line, or NULL if end-of-file
******************************************************************************/
char **get_words(FILE *fp, int *nwords, char **orig_line)
{
#define BIG_STRING 4096
static char str[BIG_STRING];
static char str_copy[BIG_STRING];
char **words;
int max_words = 10;
int num_words = 0;
char *ptr, *ptr2;
char *result;
words = (char **) myalloc(sizeof(char *) * max_words);
/* read in a line */
result = fgets(str, BIG_STRING, fp);
if (result == NULL) {
*nwords = 0;
*orig_line = NULL;
return (NULL);
}
/* convert line-feed and tabs into spaces */
/* (this guarentees that there will be a space before the */
/* null character at the end of the string) */
str[BIG_STRING - 2] = ' ';
str[BIG_STRING - 1] = '\0';
for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
*ptr2 = *ptr;
if (*ptr == '\t') {
*ptr = ' ';
*ptr2 = ' ';
}
else if (*ptr == '\n') {
*ptr = ' ';
*ptr2 = '\0';
break;
}
}
/* find the words in the line */
ptr = str;
while (*ptr != '\0') {
/* jump over leading spaces */
while (*ptr == ' ')
ptr++;
/* break if we reach the end */
if (*ptr == '\0')
break;
/* save pointer to beginning of word */
if (num_words >= max_words) {
max_words += 10;
words = (char **) realloc(words, sizeof(char *) * max_words);
}
words[num_words++] = ptr;
/* jump over non-spaces */
while (*ptr != ' ')
ptr++;
/* place a null character here to mark the end of the word */
*ptr++ = '\0';
}
/* return the list of words */
*nwords = num_words;
*orig_line = str_copy;
return (words);
}
/******************************************************************************
Return the value of an item, given a pointer to it and its type.
Entry:
item - pointer to item
type - data type that "item" points to
Exit:
returns a double-precision float that contains the value of the item
******************************************************************************/
double get_item_value(char *item, int type)
{
unsigned char *puchar;
char *pchar;
short int *pshort;
unsigned short int *pushort;
int *pint;
unsigned int *puint;
float *pfloat;
double *pdouble;
int int_value;
unsigned int uint_value;
double double_value;
switch (type) {
case PLY_CHAR:
pchar = (char *) item;
int_value = *pchar;
return ((double) int_value);
case PLY_UCHAR:
puchar = (unsigned char *) item;
int_value = *puchar;
return ((double) int_value);
case PLY_SHORT:
pshort = (short int *) item;
int_value = *pshort;
return ((double) int_value);
case PLY_USHORT:
pushort = (unsigned short int *) item;
int_value = *pushort;
return ((double) int_value);
case PLY_INT:
pint = (int *) item;
int_value = *pint;
return ((double) int_value);
case PLY_UINT:
puint = (unsigned int *) item;
uint_value = *puint;
return ((double) uint_value);
case PLY_FLOAT:
pfloat = (float *) item;
double_value = *pfloat;
return (double_value);
case PLY_DOUBLE:
pdouble = (double *) item;
double_value = *pdouble;
return (double_value);
default:
fprintf(stderr, "get_item_value: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Write out an item to a file as raw binary bytes.
Entry:
fp - file to write to
int_val - integer version of item
uint_val - unsigned integer version of item
double_val - double-precision float version of item
type - data type to write out
******************************************************************************/
void write_binary_item(
FILE *fp,
int int_val,
unsigned int uint_val,
double double_val,
int type
)
{
unsigned char uchar_val;
char char_val;
unsigned short ushort_val;
short short_val;
float float_val;
switch (type) {
case PLY_CHAR:
char_val = (char)int_val;
fwrite(&char_val, 1, 1, fp);
break;
case PLY_SHORT:
short_val = (short)int_val;
fwrite(&short_val, 2, 1, fp);
break;
case PLY_INT:
fwrite(&int_val, 4, 1, fp);
break;
case PLY_UCHAR:
uchar_val = (unsigned char) uint_val;
fwrite(&uchar_val, 1, 1, fp);
break;
case PLY_USHORT:
ushort_val = (unsigned short)uint_val;
fwrite(&ushort_val, 2, 1, fp);
break;
case PLY_UINT:
fwrite(&uint_val, 4, 1, fp);
break;
case PLY_FLOAT:
float_val = (float) double_val;
fwrite(&float_val, 4, 1, fp);
break;
case PLY_DOUBLE:
fwrite(&double_val, 8, 1, fp);
break;
default:
fprintf(stderr, "write_binary_item: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Write out an item to a file as ascii characters.
Entry:
fp - file to write to
int_val - integer version of item
uint_val - unsigned integer version of item
double_val - double-precision float version of item
type - data type to write out
******************************************************************************/
void write_ascii_item(
FILE *fp,
int int_val,
unsigned int uint_val,
double double_val,
int type
)
{
switch (type) {
case PLY_CHAR:
case PLY_SHORT:
case PLY_INT:
fprintf(fp, "%d ", int_val);
break;
case PLY_UCHAR:
case PLY_USHORT:
case PLY_UINT:
fprintf(fp, "%u ", uint_val);
break;
case PLY_FLOAT:
case PLY_DOUBLE:
fprintf(fp, "%g ", double_val);
break;
default:
fprintf(stderr, "write_ascii_item: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Write out an item to a file as ascii characters.
Entry:
fp - file to write to
item - pointer to item to write
type - data type that "item" points to
Exit:
returns a double-precision float that contains the value of the written item
******************************************************************************/
double old_write_ascii_item(FILE *fp, char *item, int type)
{
unsigned char *puchar;
char *pchar;
short int *pshort;
unsigned short int *pushort;
int *pint;
unsigned int *puint;
float *pfloat;
double *pdouble;
int int_value;
unsigned int uint_value;
double double_value;
switch (type) {
case PLY_CHAR:
pchar = (char *) item;
int_value = *pchar;
fprintf(fp, "%d ", int_value);
return ((double) int_value);
case PLY_UCHAR:
puchar = (unsigned char *) item;
int_value = *puchar;
fprintf(fp, "%d ", int_value);
return ((double) int_value);
case PLY_SHORT:
pshort = (short int *) item;
int_value = *pshort;
fprintf(fp, "%d ", int_value);
return ((double) int_value);
case PLY_USHORT:
pushort = (unsigned short int *) item;
int_value = *pushort;
fprintf(fp, "%d ", int_value);
return ((double) int_value);
case PLY_INT:
pint = (int *) item;
int_value = *pint;
fprintf(fp, "%d ", int_value);
return ((double) int_value);
case PLY_UINT:
puint = (unsigned int *) item;
uint_value = *puint;
fprintf(fp, "%u ", uint_value);
return ((double) uint_value);
case PLY_FLOAT:
pfloat = (float *) item;
double_value = *pfloat;
fprintf(fp, "%g ", double_value);
return (double_value);
case PLY_DOUBLE:
pdouble = (double *) item;
double_value = *pdouble;
fprintf(fp, "%g ", double_value);
return (double_value);
default:
fprintf(stderr, "old_write_ascii_item: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Get the value of an item that is in memory, and place the result
into an integer, an unsigned integer and a double.
Entry:
ptr - pointer to the item
type - data type supposedly in the item
Exit:
int_val - integer value
uint_val - unsigned integer value
double_val - double-precision floating point value
******************************************************************************/
void get_stored_item(
void *ptr,
int type,
int *int_val,
unsigned int *uint_val,
double *double_val
)
{
switch (type) {
case PLY_CHAR:
*int_val = *((char *) ptr);
*uint_val = *int_val;
*double_val = *int_val;
break;
case PLY_UCHAR:
*uint_val = *((unsigned char *) ptr);
*int_val = *uint_val;
*double_val = *uint_val;
break;
case PLY_SHORT:
*int_val = *((short int *) ptr);
*uint_val = *int_val;
*double_val = *int_val;
break;
case PLY_USHORT:
*uint_val = *((unsigned short int *) ptr);
*int_val = *uint_val;
*double_val = *uint_val;
break;
case PLY_INT:
*int_val = *((int *) ptr);
*uint_val = *int_val;
*double_val = *int_val;
break;
case PLY_UINT:
*uint_val = *((unsigned int *) ptr);
*int_val = *uint_val;
*double_val = *uint_val;
break;
case PLY_FLOAT:
*double_val = *((float *) ptr);
*int_val = (int)*double_val;
*uint_val = (unsigned int)*double_val;
break;
case PLY_DOUBLE:
*double_val = *((double *) ptr);
*int_val = (int)*double_val;
*uint_val = (unsigned int) *double_val;
break;
default:
fprintf(stderr, "get_stored_item: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Get the value of an item from a binary file, and place the result
into an integer, an unsigned integer and a double.
Entry:
fp - file to get item from
type - data type supposedly in the word
Exit:
int_val - integer value
uint_val - unsigned integer value
double_val - double-precision floating point value
******************************************************************************/
void get_binary_item(
FILE *fp,
int type,
int *int_val,
unsigned int *uint_val,
double *double_val
)
{
char c[8];
void *ptr;
ptr = (void *) c;
switch (type) {
case PLY_CHAR:
fread(ptr, 1, 1, fp);
*int_val = *((char *) ptr);
*uint_val = *int_val;
*double_val = *int_val;
break;
case PLY_UCHAR:
fread(ptr, 1, 1, fp);
*uint_val = *((unsigned char *) ptr);
*int_val = *uint_val;
*double_val = *uint_val;
break;
case PLY_SHORT:
fread(ptr, 2, 1, fp);
*int_val = *((short int *) ptr);
*uint_val = *int_val;
*double_val = *int_val;
break;
case PLY_USHORT:
fread(ptr, 2, 1, fp);
*uint_val = *((unsigned short int *) ptr);
*int_val = *uint_val;
*double_val = *uint_val;
break;
case PLY_INT:
fread(ptr, 4, 1, fp);
*int_val = *((int *) ptr);
*uint_val = *int_val;
*double_val = *int_val;
break;
case PLY_UINT:
fread(ptr, 4, 1, fp);
*uint_val = *((unsigned int *) ptr);
*int_val = *uint_val;
*double_val = *uint_val;
break;
case PLY_FLOAT:
fread(ptr, 4, 1, fp);
*double_val = *((float *) ptr);
*int_val = (int)*double_val;
*uint_val = (unsigned int) *double_val;
break;
case PLY_DOUBLE:
fread(ptr, 8, 1, fp);
*double_val = *((double *) ptr);
*int_val = (int)*double_val;
*uint_val = (unsigned int)*double_val;
break;
default:
fprintf(stderr, "get_binary_item: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Extract the value of an item from an ascii word, and place the result
into an integer, an unsigned integer and a double.
Entry:
word - word to extract value from
type - data type supposedly in the word
Exit:
int_val - integer value
uint_val - unsigned integer value
double_val - double-precision floating point value
******************************************************************************/
void get_ascii_item(
char *word,
int type,
int *int_val,
unsigned int *uint_val,
double *double_val
)
{
switch (type) {
case PLY_CHAR:
case PLY_UCHAR:
case PLY_SHORT:
case PLY_USHORT:
case PLY_INT:
*int_val = atoi(word);
*uint_val = *int_val;
*double_val = *int_val;
break;
case PLY_UINT:
*uint_val = strtoul(word, (char **) NULL, 10);
*int_val = *uint_val;
*double_val = *uint_val;
break;
case PLY_FLOAT:
case PLY_DOUBLE:
*double_val = atof(word);
*int_val = (int) *double_val;
*uint_val = (unsigned int) *double_val;
break;
default:
fprintf(stderr, "get_ascii_item: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Store a value into a place being pointed to, guided by a data type.
Entry:
item - place to store value
type - data type
int_val - integer version of value
uint_val - unsigned integer version of value
double_val - double version of value
Exit:
item - pointer to stored value
******************************************************************************/
void store_item(
char *item,
int type,
int int_val,
unsigned int uint_val,
double double_val
)
{
unsigned char *puchar;
short int *pshort;
unsigned short int *pushort;
int *pint;
unsigned int *puint;
float *pfloat;
double *pdouble;
switch (type) {
case PLY_CHAR:
*item = (char) int_val;
break;
case PLY_UCHAR:
puchar = (unsigned char *) item;
*puchar = (unsigned char)uint_val;
break;
case PLY_SHORT:
pshort = (short *) item;
*pshort = (short)int_val;
break;
case PLY_USHORT:
pushort = (unsigned short *) item;
*pushort = (unsigned short)uint_val;
break;
case PLY_INT:
pint = (int *) item;
*pint = int_val;
break;
case PLY_UINT:
puint = (unsigned int *) item;
*puint = uint_val;
break;
case PLY_FLOAT:
pfloat = (float *) item;
*pfloat = (float)double_val;
break;
case PLY_DOUBLE:
pdouble = (double *) item;
*pdouble = double_val;
break;
default:
fprintf(stderr, "store_item: bad type = %d\n", type);
exit(-1);
}
}
/******************************************************************************
Add an element to a PLY file descriptor.
Entry:
plyfile - PLY file descriptor
words - list of words describing the element
nwords - number of words in the list
******************************************************************************/
void add_element(PlyFile *plyfile, char **words)
{
PlyElement *elem;
/* create the new element */
elem = (PlyElement *) myalloc(sizeof(PlyElement));
elem->name = strdup(words[1]);
elem->num = atoi(words[2]);
elem->nprops = 0;
/* make room for new element in the object's list of elements */
if (plyfile->nelems == 0)
plyfile->elems = (PlyElement **) myalloc(sizeof(PlyElement *));
else
plyfile->elems = (PlyElement **) realloc(plyfile->elems,
sizeof(PlyElement *) * (plyfile->nelems + 1));
/* add the new element to the object's list */
plyfile->elems[plyfile->nelems] = elem;
plyfile->nelems++;
}
/******************************************************************************
Return the type of a property, given the name of the property.
Entry:
name - name of property type
Exit:
returns integer code for property, or 0 if not found
******************************************************************************/
int get_prop_type(char *type_name)
{
int i;
for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
if (equal_strings(type_name, type_names[i]))
return (i);
/* if we get here, we didn't find the type */
return (0);
}
/******************************************************************************
Add a property to a PLY file descriptor.
Entry:
plyfile - PLY file descriptor
words - list of words describing the property
nwords - number of words in the list
******************************************************************************/
void add_property(PlyFile *plyfile, char **words)
{
PlyProperty *prop;
PlyElement *elem;
/* create the new property */
prop = (PlyProperty *) myalloc(sizeof(PlyProperty));
if (equal_strings(words[1], "list")) { /* is a list */
prop->count_external = get_prop_type(words[2]);
prop->external_type = get_prop_type(words[3]);
prop->name = strdup(words[4]);
prop->is_list = 1;
}
else { /* not a list */
prop->external_type = get_prop_type(words[1]);
prop->name = strdup(words[2]);
prop->is_list = 0;
}
/* add this property to the list of properties of the current element */
elem = plyfile->elems[plyfile->nelems - 1];
if (elem->nprops == 0)
elem->props = (PlyProperty **) myalloc(sizeof(PlyProperty *));
else
elem->props = (PlyProperty **) realloc(elem->props,
sizeof(PlyProperty *) * (elem->nprops + 1));
elem->props[elem->nprops] = prop;
elem->nprops++;
}
/******************************************************************************
Add a comment to a PLY file descriptor.
Entry:
plyfile - PLY file descriptor
line - line containing comment
******************************************************************************/
void add_comment(PlyFile *plyfile, char *line)
{
int i;
/* skip over "comment" and leading spaces and tabs */
i = 7;
while (line[i] == ' ' || line[i] == '\t')
i++;
ply_put_comment(plyfile, &line[i]);
}
/******************************************************************************
Add a some object information to a PLY file descriptor.
Entry:
plyfile - PLY file descriptor
line - line containing text info
******************************************************************************/
void add_obj_info(PlyFile *plyfile, char *line)
{
int i;
/* skip over "obj_info" and leading spaces and tabs */
i = 8;
while (line[i] == ' ' || line[i] == '\t')
i++;
ply_put_obj_info(plyfile, &line[i]);
}
/******************************************************************************
Copy a property.
******************************************************************************/
void copy_property(PlyProperty *dest, PlyProperty *src)
{
dest->name = strdup(src->name);
dest->external_type = src->external_type;
dest->internal_type = src->internal_type;
dest->offset = src->offset;
dest->is_list = src->is_list;
dest->count_external = src->count_external;
dest->count_internal = src->count_internal;
dest->count_offset = src->count_offset;
}
/******************************************************************************
Allocate some memory.
Entry:
size - amount of memory requested (in bytes)
lnum - line number from which memory was requested
fname - file name from which memory was requested
******************************************************************************/
static char *my_alloc(int size, int lnum, char *fname)
{
char *ptr;
ptr = (char *) malloc(size);
if (ptr == 0) {
fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname);
}
return (ptr);
}