当前位置: 首页 > 编程日记 > 正文

dot3_bump_mapping

为什么80%的码农都做不了架构师?>>>   hot3.png

//-----------------------------------------------------------------------------
//           Name: ogl_dot3_bump_mapping.cpp
//         Author: Kevin Harris
//  Last Modified: 04/21/05
//    Description: This sample demonstrates how to perform Dot3 per-pixel bump 
//                 mapping using a normal map and the GL_DOT3_RGB_EXT 
//                 texture-blending operation. This technique is sometimes 
//                 referred to as per-pixel lighting or per-pixel attenuation, 
//                 but Dot3 per-pixel bump-mapping is what most programmers 
//                 know it as.
//
//                 This sample also demonstrates how to create tangent, 
//                 binormal, and normal vectors, for each vertex of our test
//                 geometry (a simple cube). These vectors are used during 
//                 rendering to define an inverse tangent matrix for each
//                 vertex. This has to be done because a normal-map stores its 
//                 normals in tangent-space. Therefore, we need an inverse 
//                 tangent matrix so we can transform our scene's light vector 
//                 from object-space into tangent-space. Once transformed, we 
//                 then encode this new light vector as a RGB color and pass 
//                 it into the texture blending stage as the vertex's Diffuse 
//                 color.
//
// Additional Notes:
//
//                 The phrase "Dot3" comes form the mathematical operation that 
//                 combines a light vector with a surface normal.
//
//                 The phrase "Per-pixel" comes from the fact that for every 
//                 pixel in the base texture map, we store a unique surface 
//                 normal to light it. These surface normals are passed into the
//                 texture blending stage via a normal-map. A normal-map is a 
//                 texture where normals (x,y,z) have been encoded and stored 
//                 as (r,g,b).
//
//   Control Keys: d/D - Toggle Dot3 bump mapping
//                 l/L - Toggle the usage of regular lighting in addition
//                       to the per-pixel lighting effect of bump mapping.
//                 m/M - Toggle motion of point light
//                 Up Arrow - Move the test cube closer
//                 Down Arrow - Move the test cube away
//-----------------------------------------------------------------------------#define STRICT
#define WIN32_LEAN_AND_MEAN#include <windows.h>
#include <mmsystem.h>
// Do this to access M_PI, which is not officially part of the C/C++ standard.
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include "geometry.h"
#include "matrix4x4f.h"
#include "vector3f.h"
#include "resource.h"//-----------------------------------------------------------------------------
// FUNCTION POINTERS FOR OPENGL EXTENSIONS
//-----------------------------------------------------------------------------// For convenience, this project ships with its own "glext.h" extension header 
// file. If you have trouble running this sample, it may be that this "glext.h" 
// file is defining something that your hardware doesn抰 actually support. 
// Try recompiling the sample using your own local, vendor-specific "glext.h" 
// header file.#include "glext.h"      // Sample's header file
//#include <GL/glext.h> // Your local header filePFNGLACTIVETEXTUREPROC       glActiveTexture       = NULL;
PFNGLMULTITEXCOORD2FPROC     glMultiTexCoord2f     = NULL;
PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTexture = NULL;//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
HDC   g_hDC  = NULL;
HGLRC g_hRC  = NULL;
HWND  g_hWnd = NULL;GLuint g_textureID = -1;
GLuint g_normalmapTextureID = -1;
bool g_bDoDot3BumpMapping = true;
bool g_bMoveLightAbout = true;
bool g_bToggleRegularLighting = false;
GLfloat g_lightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // Point Light's positionfloat g_fDistance = -5.0f;
float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;float  g_fElpasedTime;
double g_dCurTime;
double g_dLastTime;struct Vertex
{float tu, tv;float r, g, b, a;float nx, ny, nz;float x, y, z;
};const int NUM_VERTICES = 24;Vertex g_cubeVertices[NUM_VERTICES] =
{
//    tu   tv     r    g    b    a      nx    ny    nz       x     y     z // Front face{ 0.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f, 1.0f,  -1.0f,-1.0f, 1.0f },{ 1.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f, 1.0f,   1.0f,-1.0f, 1.0f },{ 1.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f, 1.0f,   1.0f, 1.0f, 1.0f },{ 0.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f, 1.0f,  -1.0f, 1.0f, 1.0f },// Back face{ 1.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f,-1.0f,  -1.0f,-1.0f,-1.0f },{ 1.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f,-1.0f,  -1.0f, 1.0f,-1.0f },{ 0.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f,-1.0f,   1.0f, 1.0f,-1.0f },{ 0.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 0.0f,-1.0f,   1.0f,-1.0f,-1.0f },// Top face{ 0.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 1.0f, 0.0f,  -1.0f, 1.0f,-1.0f },{ 0.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 1.0f, 0.0f,  -1.0f, 1.0f, 1.0f },{ 1.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 1.0f, 0.0f,   1.0f, 1.0f, 1.0f },{ 1.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f, 1.0f, 0.0f,   1.0f, 1.0f,-1.0f },// Bottom face{ 1.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f,-1.0f, 0.0f,  -1.0f,-1.0f,-1.0f },{ 0.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f,-1.0f, 0.0f,   1.0f,-1.0f,-1.0f },{ 0.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f,-1.0f, 0.0f,   1.0f,-1.0f, 1.0f },{ 1.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  0.0f,-1.0f, 0.0f,  -1.0f,-1.0f, 1.0f },// Right face{ 1.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  1.0f, 0.0f, 0.0f,   1.0f,-1.0f,-1.0f },{ 1.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  1.0f, 0.0f, 0.0f,   1.0f, 1.0f,-1.0f },{ 0.0f,1.0f,  1.0f,1.0f,1.0f,1.0f,  1.0f, 0.0f, 0.0f,   1.0f, 1.0f, 1.0f },{ 0.0f,0.0f,  1.0f,1.0f,1.0f,1.0f,  1.0f, 0.0f, 0.0f,   1.0f,-1.0f, 1.0f },// Left face{ 0.0f,0.0f,  1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f,  -1.0f,-1.0f,-1.0f },{ 1.0f,0.0f,  1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f,  -1.0f,-1.0f, 1.0f },{ 1.0f,1.0f,  1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f,  -1.0f, 1.0f, 1.0f },{ 0.0f,1.0f,  1.0f,1.0f,1.0f,1.0f, -1.0f, 0.0f, 0.0f,  -1.0f, 1.0f,-1.0f }
};// For each vertex defined above, we'll need to create a Tangent, BiNormal, and
// Normal vector, which together define a tangent matrix for Dot3 bump mapping.
vector3f g_vTangents[NUM_VERTICES];
vector3f g_vBiNormals[NUM_VERTICES];
vector3f g_vNormals[NUM_VERTICES];//-----------------------------------------------------------------------------
// PROTOTYPES
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE g_hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND g_hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void loadTexture(void);
void init(void);
void render(void);
void shutDown(void);
vector3f scaleAndBiasVectorAsRGBColor(vector3f* vVector);
void computeTangentsMatricesForEachVertex(void);
void createTangentSpaceVectors( vector3f *v1, vector3f *v2, vector3f *v3,float v1u, float v1v, float v2u, float v2v, float v3u, float v3v, vector3f *vTangent, vector3f *vBiNormal, vector3f *vNormal );//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR     lpCmdLine,int       nCmdShow )
{WNDCLASSEX winClass;MSG        uMsg;memset(&uMsg,0,sizeof(uMsg));winClass.lpszClassName = "MY_WINDOWS_CLASS";winClass.cbSize        = sizeof(WNDCLASSEX);winClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;winClass.lpfnWndProc   = WindowProc;winClass.hInstance     = hInstance;winClass.hIcon         = LoadIcon(hInstance, (LPCTSTR)IDI_OPENGL_ICON);winClass.hIconSm       = LoadIcon(hInstance, (LPCTSTR)IDI_OPENGL_ICON);winClass.hCursor       = LoadCursor(NULL, IDC_ARROW);winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);winClass.lpszMenuName  = NULL;winClass.cbClsExtra    = 0;winClass.cbWndExtra    = 0;if( !RegisterClassEx(&winClass) )return E_FAIL;g_hWnd = CreateWindowEx( NULL,"MY_WINDOWS_CLASS","OpenGL - Dot3 Per-Pixel Bump Mapping",WS_OVERLAPPEDWINDOW,0,0, 640,480, NULL, NULL, hInstance, NULL );if( g_hWnd == NULL )return E_FAIL;ShowWindow( g_hWnd, nCmdShow );UpdateWindow( g_hWnd );init();while( uMsg.message != WM_QUIT ){if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &uMsg );DispatchMessage( &uMsg );}else{g_dCurTime     = timeGetTime();g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001);g_dLastTime    = g_dCurTime;render();}}shutDown();UnregisterClass( "MY_WINDOWS_CLASS", hInstance );return uMsg.wParam;
}//-----------------------------------------------------------------------------
// Name: WindowProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc( HWND   g_hWnd, UINT   msg, WPARAM wParam, LPARAM lParam )
{static POINT ptLastMousePosit;static POINT ptCurrentMousePosit;static bool bMousing;switch( msg ){case WM_CHAR:{switch( wParam ){case 'd':case 'D':g_bDoDot3BumpMapping = !g_bDoDot3BumpMapping;break;case 'l':case 'L':g_bToggleRegularLighting = !g_bToggleRegularLighting;break;case 'm':case 'M':g_bMoveLightAbout = !g_bMoveLightAbout;break;}}break;case WM_KEYDOWN:{switch( wParam ){case VK_ESCAPE:PostQuitMessage(0);break;case 38: // Up Arrow Keyg_fDistance += 0.1f;break;case 40: // Down Arrow Keyg_fDistance -= 0.1f;break;}}break;case WM_LBUTTONDOWN:{ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam);ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam);bMousing = true;}break;case WM_LBUTTONUP:{bMousing = false;}break;case WM_MOUSEMOVE:{ptCurrentMousePosit.x = LOWORD (lParam);ptCurrentMousePosit.y = HIWORD (lParam);if( bMousing ){g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);}ptLastMousePosit.x = ptCurrentMousePosit.x;ptLastMousePosit.y = ptCurrentMousePosit.y;}break;case WM_SIZE:{int nWidth  = LOWORD(lParam); int nHeight = HIWORD(lParam);glViewport(0, 0, nWidth, nHeight);glMatrixMode( GL_PROJECTION );glLoadIdentity();gluPerspective( 45.0, (GLdouble)nWidth / (GLdouble)nHeight, 0.1, 100.0);}break;case WM_CLOSE:{PostQuitMessage(0); }case WM_DESTROY:{PostQuitMessage(0);}break;default:{return DefWindowProc( g_hWnd, msg, wParam, lParam );}break;}return 0;
}//-----------------------------------------------------------------------------
// Name: loadTexture()
// Desc: 
//-----------------------------------------------------------------------------
void loadTexture(void)
{//// Load the normal map...//AUX_RGBImageRec *pTextureImage = auxDIBImageLoad( ".\\stone_wall_normal_map.bmp" );//AUX_RGBImageRec *pTextureImage = auxDIBImageLoad( ".\\test_normal_map.bmp" );if( pTextureImage != NULL ){glGenTextures( 1, &g_normalmapTextureID );glBindTexture( GL_TEXTURE_2D, g_normalmapTextureID );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR );glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, pTextureImage->sizeX, pTextureImage->sizeY, 0,GL_RGB, GL_UNSIGNED_BYTE, pTextureImage->data );}if( pTextureImage ){if( pTextureImage->data )free( pTextureImage->data );free( pTextureImage );}//// Load the base texture//pTextureImage = auxDIBImageLoad( ".\\stone_wall.bmp" );//pTextureImage = auxDIBImageLoad( ".\\checker_with_numbers.bmp" );if( pTextureImage != NULL ){glGenTextures( 1, &g_textureID );glBindTexture( GL_TEXTURE_2D, g_textureID );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR );glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, pTextureImage->sizeX, pTextureImage->sizeY, 0,GL_RGB, GL_UNSIGNED_BYTE, pTextureImage->data );}if( pTextureImage ){if( pTextureImage->data )free( pTextureImage->data );free( pTextureImage );}
}//-----------------------------------------------------------------------------
// Name: init()
// Desc: 
//-----------------------------------------------------------------------------
void init( void )
{GLuint PixelFormat;PIXELFORMATDESCRIPTOR pfd;memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));pfd.nSize      = sizeof(PIXELFORMATDESCRIPTOR);pfd.nVersion   = 1;pfd.dwFlags    = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;pfd.iPixelType = PFD_TYPE_RGBA;pfd.cColorBits = 16;pfd.cDepthBits = 16;g_hDC = GetDC( g_hWnd );PixelFormat = ChoosePixelFormat( g_hDC, &pfd );SetPixelFormat( g_hDC, PixelFormat, &pfd);g_hRC = wglCreateContext( g_hDC );wglMakeCurrent( g_hDC, g_hRC );glClearColor( 0.35f, 0.53f, 0.7f, 1.0f );glEnable( GL_TEXTURE_2D );glEnable( GL_DEPTH_TEST );//glShadeModel( GL_FLAT );glShadeModel( GL_SMOOTH ); // Supposedly this is important to set when doing Dot3, but I notice no difference.glMatrixMode( GL_PROJECTION );glLoadIdentity();gluPerspective( 45.0f, 640.0f / 480.0f, 0.1f, 100.0f);// Set up the view matrixglMatrixMode( GL_MODELVIEW );glLoadIdentity();// For lighting, pull our material colors from the vertex color...glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );glEnable( GL_COLOR_MATERIAL );// Set light 0 to be a pure white point lightGLfloat diffuse_light0[]  = { 1.0f, 1.0f,  1.0f, 1.0f };glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse_light0 );glLightfv( GL_LIGHT0, GL_POSITION, g_lightPosition );glEnable( GL_LIGHTING );glEnable( GL_LIGHT0 );// Enable some dim, gray ambient lighting so objects that are not lit // by the other lights are not completely black.GLfloat ambient_lightModel[] = { 0.2f, 0.2f, 0.2f, 0.2f };glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient_lightModel );loadTexture();//// If the required extension is present, get the addresses of its // functions that we wish to use...////// GL_ARB_multitexture//char *ext = (char*)glGetString( GL_EXTENSIONS );if( strstr( ext, "GL_ARB_multitexture" ) == NULL ){MessageBox(NULL,"GL_ARB_multitexture extension was not found","ERROR",MB_OK|MB_ICONEXCLAMATION);return;}else{glActiveTexture       = (PFNGLCLIENTACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");glMultiTexCoord2f     = (PFNGLMULTITEXCOORD2FPROC)wglGetProcAddress("glMultiTexCoord2f");glClientActiveTexture = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glClientActiveTexture");if( !glActiveTexture || !glMultiTexCoord2f || !glClientActiveTexture ){MessageBox(NULL,"One or more GL_ARB_multitexture functions were not found","ERROR",MB_OK|MB_ICONEXCLAMATION);return;}}//// GL_EXT_texture_env_combine//if( strstr( ext, "GL_EXT_texture_env_combine" ) == NULL ){MessageBox(NULL,"GL_EXT_texture_env_combine extension was not found","ERROR",MB_OK|MB_ICONEXCLAMATION);return;}//// For each vertex, create a tangent vector, binormal, and normal//// Initialize the inverse tangent matrix for each vertex to the identity // matrix before we get started.for( int i = 0; i < NUM_VERTICES; ++i ){g_vTangents[i]  = vector3f( 1.0f, 0.0f, 0.0f );g_vBiNormals[i] = vector3f( 0.0f, 1.0f, 0.0f );g_vNormals[i]   = vector3f( 0.0f, 0.0f, 1.0f );}computeTangentsMatricesForEachVertex();}//-----------------------------------------------------------------------------
// Name: shutDown()
// Desc: 
//-----------------------------------------------------------------------------
void shutDown(void) 
{glDeleteTextures( 1, &g_textureID );glDeleteTextures( 1, &g_normalmapTextureID );if( g_hRC != NULL ){wglMakeCurrent( NULL, NULL );wglDeleteContext( g_hRC );g_hRC = NULL;                           }if( g_hDC != NULL ){ReleaseDC( g_hWnd, g_hDC );g_hDC = NULL;}
}//-----------------------------------------------------------------------------
// Name: computeTangentsMatricesForEachVertex()
// 对每一个顶点计算切线矩阵
// Desc: 
//-----------------------------------------------------------------------------
void computeTangentsMatricesForEachVertex(void)
{vector3f v1;vector3f v2;vector3f v3;vector3f vTangent;vector3f vBiNormal;vector3f vNormal;//// For each cube face defined in the vertex array, compute a tangent matrix // for each of the four vertices that define it.//for( int i = 0; i < NUM_VERTICES; i += 4 ) // Use += 4 to process 1 face at a time{//// Vertex 0 of current cube face...////  v2//    3----2//    |    |//    |    |//    0----1//  v1      v3//v1 = vector3f(g_cubeVertices[i].x,g_cubeVertices[i].y,g_cubeVertices[i].z);v2 = vector3f(g_cubeVertices[i+3].x,g_cubeVertices[i+3].y,g_cubeVertices[i+3].z);v3 = vector3f(g_cubeVertices[i+1].x,g_cubeVertices[i+1].y,g_cubeVertices[i+1].z);createTangentSpaceVectors( &v1,&v2,&v3,g_cubeVertices[i].tu, g_cubeVertices[i].tv,g_cubeVertices[i+3].tu, g_cubeVertices[i+3].tv,g_cubeVertices[i+1].tu, g_cubeVertices[i+1].tv,&vTangent, &vBiNormal, &vNormal );g_vTangents[i]  = vTangent;g_vBiNormals[i] = vBiNormal;g_vNormals[i]   = vNormal;//// Vertex 1 of current cube face...////          v3//    3----2//    |    |//    |    |//    0----1//  v2      v1//v1 = vector3f(g_cubeVertices[i+1].x,g_cubeVertices[i+1].y,g_cubeVertices[i+1].z);v2 = vector3f(g_cubeVertices[i].x,g_cubeVertices[i].y,g_cubeVertices[i].z);v3 = vector3f(g_cubeVertices[i+2].x,g_cubeVertices[i+2].y,g_cubeVertices[i+2].z);createTangentSpaceVectors( &v1,&v2,&v3,g_cubeVertices[i+1].tu, g_cubeVertices[i+1].tv,g_cubeVertices[i].tu, g_cubeVertices[i].tv,g_cubeVertices[i+2].tu, g_cubeVertices[i+2].tv,&vTangent, &vBiNormal, &vNormal );g_vTangents[i+1]  = vTangent;g_vBiNormals[i+1] = vBiNormal;g_vNormals[i+1]   = vNormal;//// Vertex 2 of current cube face...////  v3      v1//    3----2//    |    |//    |    |//    0----1//          v2//v1 = vector3f(g_cubeVertices[i+2].x,g_cubeVertices[i+2].y,g_cubeVertices[i+2].z);v2 = vector3f(g_cubeVertices[i+1].x,g_cubeVertices[i+1].y,g_cubeVertices[i+1].z);v3 = vector3f(g_cubeVertices[i+3].x,g_cubeVertices[i+3].y,g_cubeVertices[i+3].z);createTangentSpaceVectors( &v1,&v2,&v3,g_cubeVertices[i+2].tu, g_cubeVertices[i+2].tv,g_cubeVertices[i+1].tu, g_cubeVertices[i+1].tv,g_cubeVertices[i+3].tu, g_cubeVertices[i+3].tv,&vTangent, &vBiNormal, &vNormal );g_vTangents[i+2]  = vTangent;g_vBiNormals[i+2] = vBiNormal;g_vNormals[i+2]   = vNormal;//// Vertex 3 of current cube face...////  v1      v2//    3----2//    |    |//    |    |//    0----1//  v3//v1 = vector3f(g_cubeVertices[i+3].x,g_cubeVertices[i+3].y,g_cubeVertices[i+3].z);v2 = vector3f(g_cubeVertices[i+2].x,g_cubeVertices[i+2].y,g_cubeVertices[i+2].z);v3 = vector3f(g_cubeVertices[i].x,g_cubeVertices[i].y,g_cubeVertices[i].z);createTangentSpaceVectors( &v1,&v2,&v3,g_cubeVertices[i+3].tu, g_cubeVertices[i+3].tv,g_cubeVertices[i+2].tu, g_cubeVertices[i+2].tv,g_cubeVertices[i].tu, g_cubeVertices[i].tv,&vTangent, &vBiNormal, &vNormal );g_vTangents[i+3]  = vTangent;g_vBiNormals[i+3] = vBiNormal;g_vNormals[i+3]   = vNormal;}
}//-----------------------------------------------------------------------------
// Name: createTangentSpaceVectors()
// Desc: Given a vertex (v1) and two other vertices (v2 & v3) which define a 
//       triangle, this function will return Tangent, BiNormal, and Normal, 
//       vectors which can be used to define the tangent matrix for the first 
//       vertex's position (v1).
//
// Args: v1        - vertex 1
//       v2        - vertex 2
//       v3        - vertex 3
//       v1u, v1v  - texture-coordinates of vertex 1
//       v2u, v2v  - texture-coordinates of vertex 2
//       v3u, v3v  - texture-coordinates of vertex 3
//       vTangent  - When the function returns, this will be set as the tangent vector
//       vBiNormal - When the function returns, this will be set as the binormal vector
//       vNormal   - When the function returns, this will be set as the normal vector
//
// Note: This function is based on an article by By Jakob Gath and Sbren Dreijer.
// http://www.blacksmith-studios.dk/projects/downloads/tangent_matrix_derivation.php
//------------------------------------------------------------------------------void createTangentSpaceVectors( vector3f *v1,vector3f *v2,vector3f *v3,float v1u, float v1v,float v2u, float v2v,float v3u, float v3v,vector3f *vTangent,vector3f *vBiNormal,vector3f *vNormal )
{// Create edge vectors from vertex 1 to vectors 2 and 3.vector3f vDirVec_v2_to_v1 = *v2 - *v1;vector3f vDirVec_v3_to_v1 = *v3 - *v1;// Create edge vectors from the texture coordinates of vertex 1 to vector 2.float vDirVec_v2u_to_v1u = v2u - v1u;float vDirVec_v2v_to_v1v = v2v - v1v;// Create edge vectors from the texture coordinates of vertex 1 to vector 3.float vDirVec_v3u_to_v1u = v3u - v1u;float vDirVec_v3v_to_v1v = v3v - v1v;float fDenominator = vDirVec_v2u_to_v1u * vDirVec_v3v_to_v1v - vDirVec_v3u_to_v1u * vDirVec_v2v_to_v1v;if( fDenominator < 0.0001f && fDenominator > -0.0001f ){// We're too close to zero and we're at risk of a divide-by-zero! // Set the tangent matrix to the identity matrix and do nothing.*vTangent  = vector3f( 1.0f, 0.0f, 0.0f );*vBiNormal = vector3f( 0.0f, 1.0f, 0.0f );*vNormal   = vector3f( 0.0f, 0.0f, 1.0f );}else{// Calculate and cache the reciprocal valuefloat fScale1 = 1.0f / fDenominator;vector3f T;vector3f B;vector3f N;T = vector3f((vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.x - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.x) * fScale1,(vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.y - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.y) * fScale1,(vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.z - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.z) * fScale1);B = vector3f((-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.x + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.x) * fScale1,(-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.y + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.y) * fScale1,(-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.z + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.z) * fScale1);// The normal N is calculated as the cross product between T and BN = crossProduct( T, B );// Calculate and cache the reciprocal valuefloat fScale2 = 1.0f / ((T.x * B.y * N.z - T.z * B.y * N.x) + (B.x * N.y * T.z - B.z * N.y * T.x) + (N.x * T.y * B.z - N.z * T.y * B.x));//// Use the temporary T (Tangent), (B) Binormal, and N (Normal) vectors // to calculate the inverse of the tangent matrix that they represent.// The inverse of the tangent matrix is what we want since we need that// to transform the light's vector into tangent-space.//(*vTangent).x =   crossProduct( B, N ).x * fScale2;(*vTangent).y = -(crossProduct( N, T ).x * fScale2);(*vTangent).z =   crossProduct( T, B ).x * fScale2;(*vTangent).normalize();(*vBiNormal).x = -(crossProduct( B, N ).y * fScale2);(*vBiNormal).y =   crossProduct( N, T ).y * fScale2;(*vBiNormal).z = -(crossProduct( T, B ).y * fScale2);(*vBiNormal).normalize();(*vNormal).x =   crossProduct( B, N ).z * fScale2;(*vNormal).y = -(crossProduct( N, T ).z * fScale2);(*vNormal).z =   crossProduct( T, B ).z * fScale2;(*vNormal).normalize();//// NOTE: Since the texture-space of Direct3D and OpenGL are laid-out //       differently, a single normal map can't look right in both //       unless you make some adjustments somewhere.////       You can adjust or fix this problem in three ways:////       1. Create two normal maps: one for OpenGL and one for Direct3D.//       2. Flip the normal map image over as you load it into a texture //          object.//       3. Flip the binormal over when computing the tangent-space//          matrix.//// Since the normal map used by this sample was created for Direct3D,// I've decided to simply flip the binormal.//*vBiNormal = *vBiNormal * -1.0f;}
}//-----------------------------------------------------------------------------
// Name: scaleAndBiasVectorAsRGBColor()
// Desc: 
//-----------------------------------------------------------------------------
vector3f scaleAndBiasVectorAsRGBColor( vector3f* vVector )
{vector3f vScaledAndBiasedVector;vScaledAndBiasedVector.x = ((*vVector).x * 0.5f) + 0.5f;vScaledAndBiasedVector.y = ((*vVector).y * 0.5f) + 0.5f;vScaledAndBiasedVector.z = ((*vVector).z * 0.5f) + 0.5f;return vScaledAndBiasedVector;
}//-----------------------------------------------------------------------------
// Name: render()
// Desc: 
//-----------------------------------------------------------------------------
void render( void )
{// Clear the screen and the depth bufferglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );glMatrixMode( GL_MODELVIEW );glLoadIdentity();// Translate our view back a bitglTranslatef( 0.0f, 0.0f, g_fDistance );if( g_bMoveLightAbout == true ){//// Spin our point light around the cube...//static float fAngle = 0;fAngle += 60 * g_fElpasedTime;// Wrap it around, if it gets too bigwhile(fAngle > 360.0f) fAngle -= 360.0f;while(fAngle < 0.0f)   fAngle += 360.0f;float x = sinf( DEGTORAD(fAngle) );float y = cosf( DEGTORAD(fAngle) );// The call to glLightfv is just like calling glTranslatef on our// light's position.g_lightPosition[0] = 1.2f * x;g_lightPosition[1] = 1.2f * y;g_lightPosition[2] = 2.0f;glLightfv( GL_LIGHT0, GL_POSITION, g_lightPosition );}// Spin the cube via mouse input.glRotatef( -g_fSpinY, 1.0f, 0.0f, 0.0f );glRotatef( -g_fSpinX, 0.0f, 1.0f, 0.0f );//// Set texture units to some known state...//glActiveTexture(GL_TEXTURE0);glMatrixMode(GL_TEXTURE);glLoadIdentity();glMatrixMode(GL_MODELVIEW);glDisable(GL_TEXTURE_3D_EXT);glDisable(GL_TEXTURE_CUBE_MAP_ARB);glDisable(GL_TEXTURE_2D);glDisable(GL_TEXTURE_GEN_S);glDisable(GL_TEXTURE_GEN_T);glDisable(GL_TEXTURE_GEN_R);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);glActiveTexture(GL_TEXTURE1);glMatrixMode(GL_TEXTURE);glLoadIdentity();glMatrixMode(GL_MODELVIEW);glDisable(GL_TEXTURE_3D_EXT);glDisable(GL_TEXTURE_CUBE_MAP_ARB);glDisable(GL_TEXTURE_2D);glDisable(GL_TEXTURE_GEN_S);glDisable(GL_TEXTURE_GEN_T);glDisable(GL_TEXTURE_GEN_R);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);if( g_bToggleRegularLighting == true )glEnable( GL_LIGHTING );elseglDisable( GL_LIGHTING );if( g_bDoDot3BumpMapping == true ){        //// Render a Dot3 bump mapped cube...////// STAGE 0//// Use GL_DOT3_RGB_EXT to find the dot-product of (N.L), where N is // stored in the normal map, and L is passed in as the PRIMARY_COLOR// using the standard glColor3f call.//glActiveTexture(GL_TEXTURE0);glBindTexture (GL_TEXTURE_2D, g_normalmapTextureID);glEnable(GL_TEXTURE_2D);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);      // Perform a Dot3 operation...glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);           // between the N (of N.L) which is stored in a normal map texture...glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); // with the L (of N.L) which is stored in the vertex's diffuse color.glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);//// STAGE 1//// Modulate the base texture by N.L calculated in STAGE 0.//glActiveTexture(GL_TEXTURE1);glBindTexture (GL_TEXTURE_2D, g_textureID);glEnable(GL_TEXTURE_2D);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);  // Modulate...glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);    // the color argument passed down from the previous stage (stage 0) with...glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);    // the texture for this stage with.//// Transform the light's position from eye-space to object-space//vector3f vLightPosES;    // Light position (in eye-space)vector3f vLightPosOS;    // Light position (in object-space)vector3f vVertToLightOS; // L vector of N.L (in object-space)vector3f vVertToLightTS; // L vector of N.L (in tangent-space)// Get the light's current position, which is in eye-space.float fLightsPosition[4];glGetLightfv( GL_LIGHT0, GL_POSITION, fLightsPosition );vLightPosES.x = fLightsPosition[0];vLightPosES.y = fLightsPosition[1];vLightPosES.z = fLightsPosition[2];// Transform the light's position from eye-space into object-spacematrix4x4f modelViewMatrix;matrix4x4f modelViewMatrixInverse;glGetFloatv(GL_MODELVIEW_MATRIX, &modelViewMatrix.m[0] );modelViewMatrixInverse = matrix4x4f::invertMatrix( &modelViewMatrix );vLightPosOS = vLightPosES;modelViewMatrixInverse.transformPoint( &vLightPosOS );//// Now, render our textured test cube, which consists of 6 quads...//vector3f vCurrentVertex;glBegin( GL_QUADS );{for( int i = 0; i < NUM_VERTICES; ++i ){vCurrentVertex.x = g_cubeVertices[i].x;vCurrentVertex.y = g_cubeVertices[i].y;vCurrentVertex.z = g_cubeVertices[i].z;glMultiTexCoord2f( GL_TEXTURE0, g_cubeVertices[i].tu, g_cubeVertices[i].tv );glMultiTexCoord2f( GL_TEXTURE1, g_cubeVertices[i].tu, g_cubeVertices[i].tv );//// For each vertex, rotate L (of N.L) into tangent-space and // pass it into OpenGL's texture blending system by packing it // into the glVertex3f for that vertex.//vVertToLightOS = vLightPosOS - vCurrentVertex;vVertToLightOS.normalize();//// Build up an inverse tangent-space matrix using the Tangent, // Binormal, and Normal calculated for the current vertex and // then use it to transform our L vector (of N.L), which is in // object-space, into tangent-space.//// A tangent matrix is of the form://// |Tx Bx Nx 0|// |Ty By Ny 0|// |Tz Bz Nz 0|// |0  0  0  1|//// Note: Our vectors have already been inverted, so there is no // need to invert our tangent matrix once we build it up.////                         Tangent          Binormal           Normalmatrix4x4f invTangentMatrix( g_vTangents[i].x, g_vBiNormals[i].x, g_vNormals[i].x, 0.0f,g_vTangents[i].y, g_vBiNormals[i].y, g_vNormals[i].y, 0.0f,g_vTangents[i].z, g_vBiNormals[i].z, g_vNormals[i].z, 0.0f,0.0f,             0.0f,              0.0f,            1.0f );vVertToLightTS = vVertToLightOS;invTangentMatrix.transformVector( &vVertToLightTS );//// Last but not least, we must scale and bias our L vector // before passing it as a vertex color since colors have a // clamped range of [0,1]. If we don't do this any negative // components of our L vector will get clamped and the vector // will be wrong. Of course, the hardware assumes that we are // going to do this, so it will simply decode the original // vector back out by reversing the scale and bias we've // performed here.//vector3f vVertToLightTS_scaledAndBiased = scaleAndBiasVectorAsRGBColor( &vVertToLightTS );glColor3f( vVertToLightTS_scaledAndBiased.x,vVertToLightTS_scaledAndBiased.y,vVertToLightTS_scaledAndBiased.z );//glColor3f( 0.8,//	0.6,//	0.5 );glNormal3f( g_cubeVertices[i].nx, g_cubeVertices[i].ny, g_cubeVertices[i].nz );glVertex3f( vCurrentVertex.x, vCurrentVertex.y, vCurrentVertex.z );}}glEnd();/// glTranslatef(1,0,0);glDisable(GL_LIGHTING);#if 1glDisable(GL_DEPTH_TEST);glCullFace(GL_BACK);glEnable(GL_CULL_FACE);glEnable(GL_BLEND);glBlendFunc(GL_ONE,GL_ONE);glActiveTexture(GL_TEXTURE0);glBindTexture (GL_TEXTURE_2D, g_textureID);glEnable(GL_TEXTURE_2D);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);glActiveTexture(GL_TEXTURE1);glDisable(GL_TEXTURE_2D);glBegin( GL_QUADS );{for( int i = 0; i < NUM_VERTICES; ++i ){glMultiTexCoord2f( GL_TEXTURE0, g_cubeVertices[i].tu, g_cubeVertices[i].tv );glMultiTexCoord2f( GL_TEXTURE1, g_cubeVertices[i].tu, g_cubeVertices[i].tv );//glColor3f( g_cubeVertices[i].r, g_cubeVertices[i].g, g_cubeVertices[i].b );//glNormal3f( g_cubeVertices[i].nx, g_cubeVertices[i].ny, g_cubeVertices[i].nz );glVertex3f( g_cubeVertices[i].x, g_cubeVertices[i].y, g_cubeVertices[i].z );}}glEnd();glDisable(GL_BLEND);glEnable(GL_DEPTH_TEST);
#endif}else{        //// Render a regular textured cube with no Dot3 bump mapping...////// STAGE 0//glActiveTexture(GL_TEXTURE0);glBindTexture (GL_TEXTURE_2D, g_textureID);glEnable(GL_TEXTURE_2D);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);   glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);//// STAGE 1//glActiveTexture(GL_TEXTURE1);glDisable(GL_TEXTURE_2D);glBegin( GL_QUADS );{for( int i = 0; i < NUM_VERTICES; ++i ){glMultiTexCoord2f( GL_TEXTURE0, g_cubeVertices[i].tu, g_cubeVertices[i].tv );glMultiTexCoord2f( GL_TEXTURE1, g_cubeVertices[i].tu, g_cubeVertices[i].tv );glColor3f( g_cubeVertices[i].r, g_cubeVertices[i].g, g_cubeVertices[i].b );glNormal3f( g_cubeVertices[i].nx, g_cubeVertices[i].ny, g_cubeVertices[i].nz );glVertex3f( g_cubeVertices[i].x, g_cubeVertices[i].y, g_cubeVertices[i].z );}}glEnd();}//// Reset texture unit state//glActiveTexture(GL_TEXTURE0);glMatrixMode(GL_TEXTURE);glLoadIdentity();glMatrixMode(GL_MODELVIEW);glDisable(GL_TEXTURE_3D_EXT);glDisable(GL_TEXTURE_CUBE_MAP_ARB);glDisable(GL_TEXTURE_2D);glDisable(GL_TEXTURE_GEN_S);glDisable(GL_TEXTURE_GEN_T);glDisable(GL_TEXTURE_GEN_R);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);glActiveTexture(GL_TEXTURE1);glMatrixMode(GL_TEXTURE);glLoadIdentity();glMatrixMode(GL_MODELVIEW);glDisable(GL_TEXTURE_3D_EXT);glDisable(GL_TEXTURE_CUBE_MAP_ARB);glDisable(GL_TEXTURE_2D);glDisable(GL_TEXTURE_GEN_S);glDisable(GL_TEXTURE_GEN_T);glDisable(GL_TEXTURE_GEN_R);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);//// Render a small white sphere to mark the point light's position...//glDisable( GL_LIGHTING );glMatrixMode( GL_MODELVIEW );glLoadIdentity();glTranslatef( 0.0f, 0.0f, g_fDistance );glTranslatef( g_lightPosition[0], g_lightPosition[1], g_lightPosition[2] );glColor3f( 1.0f, 1.0f, 1.0f );renderSolidSphere( 0.05f, 8, 8 );glEnable( GL_LIGHTING );SwapBuffers( g_hDC );
}

转载于:https://my.oschina.net/lyr/blog/110657

相关文章:

WPF入门教程-转载

最近为了做炫酷的UI&#xff0c;了解了WPF&#xff0c;之前一直是使用winform的&#xff0c;界面也是古老的不行。在园里找到了一个大佬以前写的教程&#xff0c;备注一下。按照系列教程走下来&#xff0c;可以直接上手了。备忘传送门>>>link&#xff1a;DotNet菜园-W…

记一次shell脚本推后台stopped的问题

我们知道linux 下shell可以被分为交互式脚本和非交互式脚本。 交互式脚本即 输入命令之后shell会等待你的输入&#xff0c;当你输入之后命令会被立即提交从而执行。这个时候我们常见的终端bash&#xff0c;以及login提示等都是交互式命令。 非交互式脚本即shell解释器不需要等待…

封装,继承,多态

一、封装&#xff1a; 封装是实现面向对象程序设计的第一步&#xff0c;封装就是将数据或函数等集合在一个个的单元中&#xff08;我们称之为类&#xff09;。被封装的对象通常被称为抽象数据类型。 封装的意义&#xff1a;   封装的意义在于保护或者防止代码&#xff08;数据…

java将一个数转成36进制的数_编程实现将一个N进制数转换成M进制数。

python: 手写算法版&#xff1a; def conversion_num(num, src, dest): rtn # 1、校验源和目标是否相同 if src dest: rtn num # 2、转成10进制# if src ! 10: num_str str(num) num_str num_str[::-1] exe_num 0 dec_num 0 for num_char in num_str: # 十六进制处理 i…

iOS之Storyboard导航大揭秘(1)

本文使用的软件版本&#xff1a; IOS&#xff1a;6.1 XCode&#xff1a;4.6 Storyboard&#xff08;故事板&#xff09;是XCode4.2才开始支持的&#xff0c;为了使设计View更容易。尽管用以前的nib&#xff08;xib&#xff09;拖拖拽拽也没问题&#xff0c;不过却需要 在各种文…

nginx的gzip压缩功能

我们在开发网站的时候&#xff0c;应该要考虑到pv&#xff0c;因为pv比较大可能会造成服务器带宽不够用&#xff0c;进而导致用户体验变差。 这个时候我们就可以考虑用nginx的gzip功能。 在nginx中开启gzip压缩功能很简单&#xff0c;之需要在nginx的配置文件nginx.conf中配置以…

C语言的单链表逆序和指定范围逆序

文章目录前言逆序指定范围逆序源码实现前言 关于链表的逆置&#xff0c;是考察对链表指针的理解。知道了如何不实用额外空间&#xff0c;同时使用O(n)复杂度对链表进行逆序之后将会对链表有好理解。 同时关于如何在指定范围内对链表逆置同样可以进一步加深理解 逆序 基本过程…

mysql udf 性能_适当的mysql udf

问题不在于参数的类型,而是在调用str_ucwords_init时它是NULL(因为在检索任何行之前调用了str_ucwords_init).要使str_ucwords与字段一起使用,您必须通过在_init函数中将initid-> maybe_null设置为1并在str_ucwords中将* null_value设置为1(并且结果为NULL,尽管这可能不是必…

让Windows7运行速度更快的BIOS优化设置教程

和以前使用WindowsXP一样&#xff0c;很多用户都在设法提高windows7的系统运行速速&#xff0c;比较常见的方法大多是对系统服务进行优化&#xff0c;去掉一些可有可无的系统服务&#xff0c;还有就是优化资源管理器菜单等。除此之外&#xff0c;还有一些“不常见的偏方”&…

开源 免费 java CMS - FreeCMS1.2-功能说明-网上调查

2019独角兽企业重金招聘Python工程师标准>>> 下载地址&#xff1a;http://code.google.com/p/freecms/ 网上调查 从FreeCMS 1.2 开始支持 Admin和站点管理员可以管理站点下所有网上调查&#xff0c;普通用户只可管理自己添加的网上调查。 1. 网上调查管理 从左…

Python 之 杂谈(迭代器iter)、偏函数

1、 l [1,2,3,b,5,6] def func():return l.pop() x iter(func,b) print(x.__next__()) print(x.__next__()) print(x.__next__())执行结果&#xff1a; 遇到“b”就停下 2、偏函数 from functools import partial def add(x,y):return xy func partial(add,1)#将1固定传给x…

C语言的单链表创建:头插法/尾插法

文章目录前言链表头插法链表尾插法源码实现前言 接下来一段时间&#xff0c;将对数据结构进行复习&#xff0c;总的来说数据结构自大学之后忘记得有点吓人&#xff0c;为了防止脑容量本就小得脑袋更小&#xff0c;必须得持续性得温故了。 链表数据结构得提出 是为了弥补数组上…

java配置文件实现方式_java相关:详解Spring加载Properties配置文件的四种方式

java相关&#xff1a;详解Spring加载Properties配置文件的四种方式发布于 2020-4-29|复制链接摘记: 一、通过 context:property-placeholder 标签实现配置文件加载1、用法示例&#xff1a; 在spring.xml配置文件中添加标签..一、通过 context:property-placeholder 标签实现配置…

objective-c abort() 与 exit() 函数的区别

exit()函数 调用exit会让用户感觉程序崩溃了&#xff0c;不会有按Home键返回时的平滑过渡和动画效果&#xff1b;另外&#xff0c;使用exit可能会丢失数据&#xff0c;因为调用exit并不会调用-applicationWillTerminate:方法和UIApplicationDelegate方法&#xff1b; abort() a…

用户、组的管理常用到的命令介绍

在LINUX系统管理中&#xff0c;我们经常添加删除修改用户和组的信息&#xff0c;所以我们来学习下创建删除修改用户和组 下面我们就来简单的说下什么是组、什么是用户的概念&#xff1f; 用户&#xff1a; 其实简单的理解就是文件或者目录创建的一种标识。 组&#xff1a; 组简…

react生命周期函数

在react中&#xff0c;生命周期函数指的是组件在加载前&#xff0c;加载后&#xff0c;以及组件更新数据和组件销毁时触发的一系列方法。通常分为以下几类&#xff1a; 组件加载的时候触发的函数&#xff1a;constructor 、componentWillMount、 render 、componentDidMount 组…

C语言的单链表求交点

单链表求交点&#xff0c;问题如下&#xff1a; 使用o(1)的空间复杂度&#xff0c;求两个链表相交的时候的交点&#xff0c;这个思想就类似于使用o(1)的空间复杂度和o(n)的时间复杂度来求链表的第k个节点。 过程如下&#xff1a; 获取两个链表的长度将较长的链表移动和短链表…

jquery中如何以逗号分割字符串_百度知道

jquery中如何以逗号分割字符串_百度知道javascript本身就是带split方法的定义和用法split() 方法用于把一个字符串分割成字符串数组。语法stringObject.split(separator,howmany)参数 描述separator 必需。字符串或正则表达式&#xff0c;从该参数指定的地方分割 stringObject。…

mysql 前台启动_从Windows命令行启动MySQL

可以从命令行手动启动MySQL服务器。可以在任何版本的Windows中实现。要想从命令行启动mysqld服务器&#xff0c;你应当启动控制台窗口(或“DOS window”)并输入命令&#xff1a;C&#xff1a;\> C:\Program Files\MySQL\MySQL Server 5.0\bin\mysqld根据系统中MySQL安装位置…

设置datagridview的数据源为(DATASET)SQL查寻结果

private void button5_Click(object sender, EventArgs e)02 {03 if (MessageBox.Show("确认删除该行吗&#xff1f;", "删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) DialogResult.Yes )04 {05 SqlConnection conn new SqlConnection();0…

vim中文手册

http://vimcdoc.sourceforge.net/doc/help.html转载于:https://www.cnblogs.com/answercard/p/10125611.html

C语言单链表求环,并返回环的起始节点

若链表中存在环&#xff0c;找出其中的环所在的节点&#xff0c;否则&#xff0c;返回NULL 在没有C set容器的优势前提下&#xff0c;我们对这样的环型的寻找以及定位可以利用快慢指针来实现。 有环的存在&#xff0c;类似与操场跑圈&#xff0c;必然存在快慢之分。有了快慢&a…

CSS3无前缀脚本prefixfree.js与Animatable使用介绍

要求 必备知识 本文要求基本了解 JAVASCRIPT 和 和 CSS3 基本知识。 运行环境 桌面端:IE9 &#xff0c;Opera 10&#xff0c;火狐3.5 &#xff0c;Safari 4和Chrome浏览器;移动端:移动Safari&#xff0c;Android浏览器&#xff0c;Chrome浏览器和Opera Mobile。 演示地址 演示…

mysql的优化之table_open_cache 篇_mysql性能优化之table_open_cache

表现&#xff1a;数据库查询效率慢&#xff0c;show processlist 发现比较多的查询正在opening table。进一步确认&#xff0c;执行以下语句&#xff1a;mysql> show global status like open%tables%;------------------------| Variable_name | Value |----------------…

AIX系统日志学习笔记之一

AIX系统上线之后&#xff0c;难免会出现错误&#xff0c;为了应对错误&#xff0c;aix提供了很多处理错误的方法和日志记录机制&#xff0c;为修复故障和系统提供方便。 Errdemon是aix的一个守护进程&#xff0c;该进程会实时检查/dev/drror设备文件&#xff0c;查看是否有新的…

C语言的单链表分割

已知链表头指针head与数值x&#xff0c;将所有小于x的节点放在大于或等于x 的节点前&#xff0c;且保持这些节点的原来的相对位置。 这个过程有点类似于快速排序&#xff0c;寻找一个阈值&#xff0c;比该阈值小的放左边&#xff0c;比该阈值大的放右边。只是由数组遍历变为来…

java面试时候算法题多吗_java程序员面试中最容易被问到的18个算法题(附答案!)...

作者&#xff1a;cpp软件架构狮链接&#xff1a;https://www.toutiao.com/i6618515311836529156/(点击阅读原文前去围观)算法是比较复杂又基础的学科&#xff0c;每个学编程的人都会学习大量的算法。而根据统计&#xff0c;以下这18个问题是面试中最容易遇到的&#xff0c;本文…

Ubantu Mark

说明&#xff1a;由于图形化界面方法&#xff08;如Add/Remove... 和Synaptic Package Manageer&#xff09;比较简单&#xff0c;所以这里主要总结在终端通过命令行方式进行的软件包安装、卸载和删除的方法。 一、Ubuntu中软件安装方法 1、APT方式 &#xff08;1&#xff09;普…

Linux挂载Windows共享目录

手工挂载&#xff1a; mount -t cifs -o usernameXXX,passwordXXX //IP/共享目录 /挂载目录 自动挂载&#xff1a; 在etc/fstab加入 //IP/共享目录 /挂载目录 cifs defaults,auto,usernameXXX,passwordXXX 0 0 重启转载于:https://blog.51cto.com/kenzhuang/1149033

搭建私有npm私库(使用verdaccio)

一、为什么要搭建npm私库 原因:1&#xff09;公司内部开发的私有包&#xff0c;统一管理&#xff0c;方便开发和使用&#xff1b;2&#xff09;安全性&#xff0c;由于公司内部开发的模块和一些内容并不希望其他无关人员能够看到&#xff0c;但是又希望内部能方便使用&#xff…