?? hairmain.cpp
字號:
/**********************************************************/
/* */
/* HairMain.cpp */
/* Steve Sloan II */
/* March 2003 */
/* */
/**********************************************************/
#include <math.h>
#include <GL/glut.h>
#include <string.h>
#include "GL/glui.h"
#include "utils.h"
#include "decal.h"
#include "HairGuides.h"
#include "ToolMarker.h"
#define MAXPATH 1024
#define FILECHOICES 9
#define DEFAULTFILE 4
#define DEFAULTSPACING 20
#define ORTHOWIDTH 0.8
#define FILE_CHOICE_ID 111
#define PERSP_CHECK_ID 112
#define HAIRSPACING_ID 113
static char scFileList[FILECHOICES][MAXPATH] = {
"c:\\temp\\tgatest.tga",
"c:\\temp\\colortest.tga",
"c:\\temp\\blurtest.tga",
"c:\\temp\\bobble08.tga",
"c:\\temp\\jgfronta.tga",
"c:\\temp\\14by11.tga",
"c:\\temp\\16by12.tga",
"c:\\temp\\bobble08_full.tga",
"c:\\temp\\threeby3.tga"
};
// GLUI Elements
/** These are the live variables passed into GLUI ***/
int bSpin = 0;
int bPersp = 0;
int nHairSpacing = DEFAULTSPACING;
int mainWindow;
int ScreenWidth = 0;
int ScreenHeight = 0;
GLUI_Rotation *glui_rotate;
float mTrackball[16];
GLUI_Listbox *glui_FileSectionLB;
int FileSelection = DEFAULTFILE;
GLUI_Spinner *spacing_spinner;
GLUI_Panel *glui_hairsettings;
GLUI_Panel *glui_view;
GLuint nCursorPos = 0;
// Texture Info
Decal *CurrentDecal;
HairGuides HairArray;
ToolMarker Cursor;
GLdouble projmatrix[16];
// PrintPicture
// Input: tgaInfo*
// Output: void
// An early test function, confirming that the TGA reader works
void PrintPicture(tgaInfo *info)
{
int mode, i, j, cursor;
unsigned char grayscale = 0;
printf(" width = %4d\n", info->width);
printf(" height = %4d\n", info->height);
// compute the number of actual components
mode = info->pixelDepth / 8;
for (j = (info->height - 1); j >= 0; j--)
{
printf("[");
for (i = 0; i < info->width; i ++)
{
cursor = mode * (j * info->width + i);
grayscale = (unsigned char)(0.30 * info->imageData[cursor] +
0.59 * info->imageData[cursor+1] +
0.11 * info->imageData[cursor+2]);
if (grayscale > 128)
printf("X");
else
printf(" ");
}
printf("]\n");
}
}
// DoPicture
// Input: char*
// Output: void
// Opens the TGA file specified by sFileName, copies its
// data into a texture with power-of-two dimensions, then
// sets up the texture for use in OpenGL
void DoPicture(char* sFileName)
{
if (CurrentDecal)
CurrentDecal->SetDecal(sFileName);
else
CurrentDecal = new Decal(sFileName);
CurrentDecal->InitGLTexture();
HairArray.SetTextureInfo(CurrentDecal);
HairArray.SetPixelSpacing(nHairSpacing);
Cursor.SetTextureInfo(CurrentDecal);
Cursor.CreateDisplayList();
}
// DoReshape
// Input: void
// Output: void
// Do the actual work behind myGlutReshape
void DoReshape()
{
glViewport( 0, 0, ScreenWidth, ScreenHeight );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
float xy_aspect = (float)ScreenWidth / (float)ScreenHeight;
if (bPersp)
{
glFrustum( -xy_aspect*.08, xy_aspect*.08, -.08, .08, .1, 15.0 );
}
else
{
float scaled_aspect = xy_aspect * ORTHOWIDTH;
glOrtho( -scaled_aspect, scaled_aspect, -ORTHOWIDTH, ORTHOWIDTH, -10.0, 10.0 );
}
// Store the new projection matrix
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
// Refresh the screen
glutPostRedisplay();
}
void MoveCursor()
{
/*
if ( ( nCursorPos > CurrentDecal->nPixelTextureWidth ) || ( nCursorPos > CurrentDecal->nPixelTextureHeight ) )
nCursorPos = 0;
else
nCursorPos++;
Cursor.SetPixelPos( nCursorPos, nCursorPos );
*/
}
// myGlutIdle
// Input: void
// Output: void
// Called when the program isn't doing anything else
void myGlutIdle( void )
{
// According to the GLUT specification, the current window is
// undefined during an idle callback. So we need to explicitly
// change it if necessary
if ( glutGetWindow() != mainWindow )
glutSetWindow(mainWindow);
MoveCursor();
glutPostRedisplay();
}
// myGlutReshape
// Input: w, h = New width and height of the window
// Output: void
// Update the screen's proportions when the window resizes
void myGlutReshape(int w, int h)
{
ScreenWidth = w;
ScreenHeight = h;
DoReshape();
}
// myGlutDisplay
// Input: void
// Output: void
// Display the scene
void myGlutDisplay(void)
{
static float rotationX = 0.0, rotationY = 0.0;
GLuint i = 0;
glClearColor( .9f, .9f, .9f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
/*** Rotate the object ***/
rotationX += 3.3f;
rotationY += 4.7f;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -1.0 );
if (bSpin)
{
glRotatef( rotationY, 0.0, 1.0, 0.0 );
glRotatef( rotationX, 1.0, 0.0, 0.0 );
}
else
{
glMultMatrixf(mTrackball);
}
CurrentDecal->DoTransform();
GLfloat fPlaneDif[] = {1.0, 1.0, 1.0, 1.0};
GLfloat fPlaneAmb[] = {0.0, 0.0, 0.0, 1.0};
GLfloat fPlaneSpec[] = {1.0, 1.0, 1.0, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fPlaneDif);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, fPlaneAmb);
CurrentDecal->Draw();
HairArray.Draw();
Cursor.Draw();
glutSwapBuffers();
}
GLdouble dClamp(GLdouble val, GLdouble min, GLdouble max)
{
if (val > max) return max;
if (val < min) return min;
return val;
}
void PlaceCursor(int mousex, int mousey)
{
GLint viewport[4];
GLdouble mvmatrix[16];
GLdouble x1, y1, z1;
GLdouble x2, y2, z2;
GLdouble t;
GLdouble wx, wy;
GLint realy;
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
// Get the "mouse line", from the mouse directly into the screen, in world coordinates
realy = viewport[3] - (GLint) mousey - 1;
gluUnProject( (GLdouble) mousex, (GLdouble) realy, 0.0,
mvmatrix, projmatrix, viewport, &x1, &y1, &z1 );
gluUnProject( (GLdouble) mousex, (GLdouble) realy, 1.0,
mvmatrix, projmatrix, viewport, &x2, &y2, &z2 );
// Compute where the "mouse line" intersects z = 0
t = z1 / (z1 - z2);
wx = x1 + t * (x2 - x1);
wy = y1 + t * (y2 - y1);
wx = dClamp(wx, 0.0, CurrentDecal->fPhysicalTextureWidth);
wy = dClamp(wy, 0.0, CurrentDecal->fPhysicalTextureHeight);
Cursor.SetWorldPos(wx, wy);
}
// myGlutPassiveMotion
// Input: void
// Output: void
// Display the scene
void myGlutPassiveMotion(int x, int y)
{
// printf("Passive x, y = (%5d, %5d)\n", x, y);
PlaceCursor(x, y);
}
// myGlutMouse
// Input: void
// Output: void
// Display the scene
void myGlutMouse(int button, int state, int x, int y)
{
switch (button)
{
case GLUT_LEFT_BUTTON:
printf("L ");
break;
case GLUT_MIDDLE_BUTTON:
printf("M ");
break;
case GLUT_RIGHT_BUTTON:
printf("R ");
break;
}
switch (state)
{
case GLUT_UP:
printf("U ");
break;
case GLUT_DOWN:
printf("D ");
break;
}
// printf(" x, y = (%5d, %5d)\n", x, y);
PlaceCursor(x, y);
}
// myGlutMotion
// Input: void
// Output: void
// Display the scene
void myGlutMotion(int x, int y)
{
// printf("button down x, y = (%5d, %5d)\n", x, y);
PlaceCursor(x, y);
}
// glui_control
// Input: control = ID of the control that changed
// Output: void
// React to changes in the widget data
void glui_control( int control )
{
switch(control) {
case FILE_CHOICE_ID:
FileSelection = glui_FileSectionLB->get_int_val();
DoPicture(scFileList[FileSelection]);
break;
case PERSP_CHECK_ID:
DoReshape();
break;
case HAIRSPACING_ID:
// Update the value
nHairSpacing = spacing_spinner->get_int_val();
// Change the spacing to match
HairArray.SetPixelSpacing(nHairSpacing);
// Refresh the screen
glutPostRedisplay();
break;
}
}
// Cleanup
// Input: void
// Output: void
// Delete any data structures
void Cleanup()
{
if (CurrentDecal)
{
delete CurrentDecal;
CurrentDecal = NULL;
}
}
// quit
// Input: status = program exit status
// Output: void
// Stuff to do when the program exits
void quit(int status) {
Cleanup();
exit(status);
}
void PrintVectorAngle(double x, double y)
{
double angle = GetVectorAngle(x, y);
printf("angle(%7.2f, %7.2f) = %7.2f\n", x, y, angle);
}
// main
// Input: argc, argv = program command line arguments
// Output: void
// Main body of the program
int main(int argc, char **argv)
{
int i;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0,0);
glutInitWindowSize(500,500);
mainWindow = glutCreateWindow("TGA Test");
GLUI_Master.set_glutReshapeFunc(myGlutReshape);
GLUI_Master.set_glutDisplayFunc(myGlutDisplay);
GLUI_Master.set_glutMouseFunc(myGlutMouse);
glutMotionFunc(myGlutMotion);
glutPassiveMotionFunc(myGlutPassiveMotion);
CurrentDecal = NULL;
PrintVectorAngle( 0.0, 0.0); // 0
PrintVectorAngle( 0.0, 1.0); // 0
PrintVectorAngle( 1.0, 1.0); // 45
PrintVectorAngle( 1.0, 0.0); // 90
PrintVectorAngle( 2.0, -1.0); // ~117
PrintVectorAngle( 0.0, -1.0); // 180
PrintVectorAngle(-2.0, -1.0); // ~243
PrintVectorAngle(-1.0, 0.0); // 270
PrintVectorAngle(-1.0, 2.0); // ~333
/****************************************/
/* Set up OpenGL lights */
/****************************************/
// GLfloat light0_ambient[] = {0.1f, 0.1f, 0.3f, 1.0f};
// GLfloat light0_diffuse[] = {.6f, .6f, 1.0f, 1.0f};
GLfloat light0_ambient[] = {0.05f, 0.05f, 0.05f, 1.0f};
GLfloat light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat light0_position[] = {1.0f, 1.0f, 1.0f, 0.0f};
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
/****************************************/
/* Enable z-buferring */
/****************************************/
glEnable(GL_DEPTH_TEST);
/* Get texture */
DoPicture(scFileList[DEFAULTFILE]);
/****************************************/
/* Here's the GLUI code */
/****************************************/
GLUI *glui = GLUI_Master.create_glui( "GLUI" );
glui_FileSectionLB = glui->add_listbox("Image File:",
NULL,FILE_CHOICE_ID,glui_control);
// Fill the file list box
for (i = 0; i < FILECHOICES; i++)
glui_FileSectionLB->add_item( i, scFileList[i] );
// Set the list box to the default
glui_FileSectionLB->set_int_val(DEFAULTFILE);
glui_hairsettings = glui->add_panel("Hair Settings");
spacing_spinner = glui->add_spinner_to_panel( glui_hairsettings, "Guide Hair Spacing:",
GLUI_SPINNER_INT, NULL, HAIRSPACING_ID, glui_control );
spacing_spinner->set_int_val( DEFAULTSPACING );
spacing_spinner->set_int_limits( 1, 1000 );
// Set up the rotation "trackball"
glui_view = glui->add_panel("View");
glui_rotate = glui->add_rotation_to_panel( glui_view, "Rotation", mTrackball );
glui_rotate->set_spin( 0.95 );
glui_rotate->reset();
glui->add_checkbox_to_panel( glui_view, "Perspective", &bPersp, PERSP_CHECK_ID, glui_control );
glui->add_checkbox_to_panel( glui_view, "Spin?", &bSpin );
// Quit button
glui->add_button( "Quit", 0,quit);
glui->set_main_gfx_window( mainWindow );
/* We register the idle callback with GLUI, *not* with GLUT */
GLUI_Master.set_glutIdleFunc( myGlutIdle );
glutMainLoop();
Cleanup();
return(0);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -