/*Magic2D.cpp文件:
可以播放《爱你一万年》歌曲,需要在工程文件夹中新建文件夹“sound”并存放“爱你一万年.wav”文件
需要在Data文件夹中上传y2.bmp到y7.bmp的图片,当然也可以在程序中相应部分自己修改
该程序有两个文件,Magic2D.cpp和MoFang.cpp,可以实现三阶魔方任意层面的旋转并能使魔方在界面来回移动反弹,具体的建工程的步骤就不说了,祝大家好运*/
#include "MoFang.h"
#include
#pragma comment(lib, "WINMM.LIB") //导入winmm.lib库,实现对多媒体编程的支持
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
bool keys[256]; // Array Used For The Keyboard Routine
HINSTANCE hInstance; // Holds The Instance Of The Application
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
GLfloat xrot; // X Rotation ( NEW )
GLfloat yrot; // Y Rotation ( NEW )
GLfloat zrot; // Z Rotation ( NEW )
GLfloat RX=0;
GLfloat RY=0;
GLuint texture[7]; // Storage For One Texture ( NEW )
GLboolean b_RX,b_RY;
GLfloat turn_x=1,turn_y=1;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // CALLBACK代表回调函数Declaration For WndProc,函数声明,监听windows
AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
FILE *File=NULL; // File Handle
if (!Filename) // Make Sure A Filename Was Given
return NULL; // If Not Return NULL }
File=fopen(Filename,"r"); // Check To See If The File Exists
if (File) // Does The File Exist?
{
fclose(File); // Close The Handle
return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
}
return NULL; // If Load Failed Return NULL
}
void loadsound()
{
PlaySound("sound\\爱你一万年.wav",NULL,SND_LOOP|SND_ASYNC|SND_FILENAME);
}
int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
int Status=FALSE; // Status Indicator
AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]=LoadBMP("Data/NeHe.bmp"))
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[0]); // Create The Texture
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure }
return Status; // Return The Status
}
int LoadGLTextures(char *file,int index) // Load Bitmaps And Convert To Textures
{
int Status=FALSE; // Status Indicator
AUX_RGBImageRec *TextureImage[1]; // 创建纹理储存空间
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]=LoadBMP(file))
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[index]); // 生成纹理
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texture[index]); //glBindTexture函数实现了将调用glGenTextures函数生成的纹理的名字绑定到对应的目标纹理上。
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure }
return Status; // Return The Status
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By {
height=1; // Making Height Equal One }
glViewport(0,0,width,height); // 按照指定的高和宽显示图像Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); //使图像显示时自身比例相同,不会产生扭曲,图像在z轴方向上的坐标必须介于-0.1到-100之间,不然显示不出来
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // 使原点重新回到屏幕中心Reset The Modelview Matrix
}
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
if (!LoadGLTextures("Data/y2.bmp",1)) // 生成纹理texture[1]
{
return FALSE; // If Texture Didn't Load Return FALSE
}
if (!LoadGLTextures("Data/y3.bmp",2)) // Jump To
Texture Loading Routine ( NEW )
{
return FALSE; // If Texture Didn't Load Return FALSE
}
if (!LoadGLTextures("Data/y4.bmp",3)) // Jump To Texture Loading Routine ( NEW )
{
return FALSE; // If Texture Didn't Load Return FALSE
}
if (!LoadGLTextures("Data/y5.bmp",4)) // Jump To Texture Loading Routine ( NEW )
{
return FALSE; // If Texture Didn't Load Return FALSE
}
if (!LoadGLTextures("Data/y6.bmp",5)) // Jump To Texture Loading Routine ( NEW )
{
return FALSE; // If Texture Didn't Load Return FALSE
}
if (!LoadGLTextures("Data/y7.bmp",6)) // Jump To Texture Loading Routine ( NEW )
{
return FALSE; // If Texture Didn't Load Return FALSE
}
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
glShadeModel(GL_SMOOTH); // Enable Smooth Shading,启用阴影平滑
glClearColor(0.5f, 0.0f, 0.0f, 0.5f); // Black Background,背景设为黑色
glClearDepth(1.0f); // Depth Buffer Setup,设置深度缓存
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective
Calculations
loadsound();
return TRUE; // Initialization Went OK
}
void DrawObject(int ID) //画出一个立方体,六个面,贴图
{
stPoint *CubePoint = Cube[ID].CubePoint;
// Front Face
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin(GL_QUADS); //发布四边形绘图指令glTexCoord2f(0.0f, 0.0f); glVertex3fv( CubePoint[0].p);//glTexCoord2f指定平面纹理坐标,glVertex3fv是四边形的顶点坐标
glTexCoord2f(1.0f, 0.0f); glVertex3fv( CubePoint[1].p);
glTexCoord2f(1.0f, 1.0f); glVertex3fv( CubePoint[2].p);
glTexCoord2f(0.0f, 1.0f); glVertex3fv( CubePoint[3].p);
glEnd();
// Back Face
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3fv( CubePoint[4].p);
glTexCoord2f(1.0f, 1.0f); glVertex3fv( CubePoint[5].p);
glTexCoord2f(0.0f, 1.0f); glVertex3fv( CubePoint[6].p);
glTexCoord2f(0.0f, 0.0f); glVertex3fv( CubePoint[7].p);
glEnd();
// Top Face
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3fv( CubePoint[5].p);
glTexCoord2f(0.0f, 0.0f); glVertex3fv( CubePoint[3].p);
glTexCoord2f(1.0f, 0.0f); glVertex3fv( CubePoint[2].p);
glTexCoord2f(1.0f, 1.0f); glVertex3fv( CubePoint[6].p);
glEnd();
// Bottom Face
glBindTexture(GL_TEXTURE_2D, texture[4]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3fv( CubePoint[4].p);
glTexCoord2f(0.0f, 0.0f); glVertex3fv( CubePoint[7].p);
glTexCoord2f(0.0f, 1.0f); glVertex3fv( CubePoint[1].p);
glTexCoord2f(1.0f, 1.0f); glVertex3fv( CubePoint[0].p);
glEnd();
// Right face
glBindTexture(GL_TEXTURE_2D, texture[5]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3fv( CubePoint[7].p);
glTexCoord2f(1.0f, 1.0f); glVertex3fv( CubePoint[6].p);
glTexCoord2f(0.0f, 1.0f); glVertex3fv( CubePoint[2].p);
glTexCoord2f(0.0f, 0.0f); glVertex3fv( CubePoint[1].p);
glEnd();
// Left Face
glBindTexture(GL_TEXTURE_2D, texture[6]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3fv( CubePoint[4].p);
glTexCoord2f(1.0f, 0.0f); glVertex3fv( CubePoint[0].p);
glTexCoord2f(1.0f, 1.0f); glVertex3fv( CubePoint[3].p);
glTexCoord2f(0.0f, 1.0f); glVertex3fv( CubePoint[5].p);
glEnd();
}
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
int i;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-12.0f); // glTranslatef为坐标系原点平移函数,相当于相对平面向里面平移12,
glTranslatef(RX,0.0f,0.0f);
glTranslatef(0.0,RY,0.0);
glRotatef(xrot,1.0f,0.0f,0.0f); // 整体的旋转靠库函数来实现,glRotatef为坐标系旋转函数
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);
for (i=0;i<27;i++)
{
DrawObject(i);
}
xrot+=0.2f;
yrot+=0.2f;
zrot+=0.2f; //控制魔方整体的旋转
return TRUE; // Keep Going
}
GLvoid KillGLWindow(GLvoid) // Properly Kill The Window {
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer }
if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL }
if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL }
if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL }
if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class {
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL }
}
/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color (8/16/24/32) *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height
fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE }
if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if
(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) {
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE }
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE }
}
}
if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer全屏则隐去光标
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style }
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // 不管全屏或者非全屏,都将屏幕调整到要求的大小
// Create The Window
if (!(hWnd=CreateWindowEx( d wExStyle, // Extended Style For The Window
"OpenGL", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored };
if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen reset_model();
if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
return TRUE; // Success
}
static int iii=0;
LRESULT CALLBACK WndProc( H WND hWnd, // Handle For This Window 此函数是为了监听windows,只处理参数uMsg
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) //处理系统向应用程序发送的信息{
case WM_ACTIVATE: // 0x0006,Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active }
return 0; // Return To The Message Loop }
case WM_SYSCOMMAND: // 0x0112,Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}
case WM_CLOSE: // 0x0010,Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}
case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}
case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}
case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
case WM_TIMER: //Timer1的消息由WM_TIMER 接收并处理,以实现立方体的旋转
{
if(rotAngle != 0) //如果旋转角度不为零
{
if(rotZ==1)
Rotate_ZM();
if(rotZ==2)
Rotate_ZS();
if(rotZ==3)
Rotate_ZP();
if(rotY==1)
Rotate_YM();
if(rotY==2)
Rotate_YS();
if(rotY==3)
Rotate_YP();
if(rotX==1)
Rotate_XM();
if(rotX==2)
Rotate_XS();
if(rotX==3)
Rotate_XP();
}
}
}
return DefWindowProc(hWnd,uMsg,wParam,lParam); // Pass All Unhandled Messages To DefWindowProc
}
VOID CALLBACK TimerProc( //Timer2的消息由TimerProc函数处理,用于生成控制量以控制旋转轴和旋转方向。
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // Specifies the timer's identifier.
DWORD dwTime // current system time
)
{
if( idEvent==2)
{
int r = rand(); //随机数
if( r%18==0)
enable_XM_roatate(1);
else if( r%18==1)
enable_XS_roatate(1);
else if( r%18==2)
enable_XP_roatate(1);
else if( r%18==3)
enable_XM_roatate(-1);
else if( r%18==4)
enable_XS_roatate(-1);
else if( r%18==5)
enable_XP_roatate(-1);
else if( r%18==6)
enable_YM_roatate(1);
else if( r%18==7)
enable_YS_roatate(1);
else if( r%18==8)
enable_YP_roatate(1);
else if( r%18==9)
enable_YM_roatate(-1);
else if( r%18==10)
enable_YS_roatate(-1);
else if( r%18==11)
enable_YP_roatate(-1);
else if( r%18==12)
enable_ZM_roatate(1);
else if( r%18==13)
enable_ZS_roatate(1);
else if( r%18==14)
enable_ZP_roatate(1);
else if( r%18==15)
enable_ZM_roatate(-1);
else if( r%18==16)
enable_ZS_roatate(-1);
else if( r%18==17)
enable_ZP_roatate(-1);
}
}
VOID CALLBACK CubeWalk( //定时器
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime // current system time
)
{
if(idEvent==3)
{
if(fabs(RX+8)<0.01||fabs(RX-8)<0.01)
{
turn_x=(-turn_x);
}
else if(fabs(RY+4)<0.01||fabs(RY-4)<0.01)
{
turn_y=(-turn_y);
}
RX+=(turn_x*0.01);
RY+=(turn_y*0.01);
}
}
//程序入口。实现Windows窗体的建立和消息循环,在消息循环中实现键盘、鼠标输入事件处理响应
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
//RECT WindowRect;
// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // Windowed Mode选择是否全屏运行
}
// Create Our OpenGL Window创建窗体
if (!CreateGLWindow("xxxxxx班Uxxxxxxxxx",1280,768,16,fullscreen))
{
return 0; // Quit If Window Was Not Created }
::SetTimer(hWnd,1,2,NULL); //timer identifier=1,time-out value=5,用NULL的话,系统会把SetTimer产生的消息加入消息队列中
::SetTimer(hWnd,2,1,TimerProc); //TimerProc为回调函数的指针,Pointer to the function to be notified when the time-out value elapses
::SetTimer(hWnd,3,0.5,CubeWalk); //意思是每0.5毫秒触发一次该定时器
while(!done) // Loop That Runs While done=FALSE {
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message }
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done=TRUE; // ESC or DrawGLScene Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
SwapBuffers(hDC); // Swap Buffers (Double Buffering) }
if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("NeHe's Texture Mapping Tutorial",640,480,16,fullscreen))
{
三阶魔方公式、魔方图解、魔方教程,从零基础到精通! 魔方还原法Rubic's Cube Solution ————先看理论“ 魔方的还原方法很多 在这里向大家介绍一种比较简单的魔方六面还原方法。这种方法熟练之后可以在大约30秒之内将魔方的六面还原。 在介绍还原法之前,首先说明一下魔方移动的记法。魔方状态图中标有字母“F”的为前面,图后所记载的操作都以这个前面为基准。各个面用以下字母表示: F:前面 U:上面 D:下面 L:左面 R:右面 H:水平方向的中间层 V:垂直方向的中间层 魔方操作步骤中,单独写一个字母表示将该面顺时针旋转90度,字母后加一个减号表示将该面逆时针旋转90度,字母后加一个数字2表示将该面旋转180度。H的情况下,由上向下看来决定顺逆时针方向;V的情况下,由右向左看来决定顺逆时针方向。例如 U:将上层顺时针旋转90度 L-:将左面逆时针旋转90度 H2:将水平中间层旋转180度 目录 上层四角还原 下层四角还原 上下层八角还原 上下层边块还原 中层边块还原 上层四角还原 首先我们用最简单的几步使得上层的三个角块归位,暂不必考虑四周的色向位置)。还有一个角块存在五种情况,归位方法如下。 L D L- F- D- F D L2 D- L2 F L D- L- L- F- D F
下层四角还原 上层四角归位后,将上层放在下面位置上,作为下层。然后看上层和四周的颜色和图案排列,按照以下的操作使上层四个角块一次归位。共存在七种情况。 R2 U2 R- U2 R2 R- U- F- U F U- F- U F R R U R- U R U2 R- L- U- L U- L- U2 L R- U- F- U F R R U R- U- F- U- F R U- R- U- F- U F 上下层八角还原 要是上层和下层八个角块色向位置全部相同,存在下面五种情况: 当上下二层八个角块色向位置都不对时:按照(1)旋转。 当下层四个角块色向位置不对,上层相邻两个角块色相位置对时:将上层色向位置相同的两个角块放在后面位置上,按照(2)旋转。 当下层四个角块色向位置对,上层相邻两个角块色相位置也对时:将上层色向位置相同的两个角块放在前面位置上,按照(2)旋转后即变成第一种情况。 当下层四个角块色向位置对,上层四个角块色向位置不对时:按照(2)旋转后即变成第二种情况。 当下层相邻两个角块色向位置对,上层相邻两个角块色向位置也对时:将下层色向位置相同的两个角块放在右面位置上,上层色相位置相同的两个角块放在前面位置上,按照(2)旋转之后即变成第二种情况。 (1) R2 F2 R2 (2) R- D F- D2 F D- R 上下层边块还原 按照下图所示操作方法将上下层的边块归位。在上层边块归位时,要注意四周的色向位置。留下一个边块不必马上归位,留作下层边块归位时调整使用。 上层三个边块归位之后,将该层放在下面位置上作为下层,然后将上层的四个边块归位。操作时,为了不破坏下层已经归位的边块,必须将下层留下的一个未归位的边块垂直对着上层要归位的边块的位置。 R- H- R R H R- F H- F- V- D2 V F H- F2 H2 F
我们用的是降阶法,基本的还原过程如下: 1.中心复原 2.棱合并 3.按三阶还原 4.特殊情况校正 四阶魔方与三阶魔方的区别主要有两点,1.中心块的相对位置不是固定的,也就是说,你可能轻易对出四个黄中红中心块的情况,但是如果对成这样后面就不能还原了,你需要自己在前面几步注意做好中心块的相对位置关系,图所示,上黄下白前红后橙左蓝右绿,然后再继续后面的步骤。2.四阶魔方对好中心块,合并好棱边后,就个三阶魔方,但是这个三阶魔方会出现我们三阶入门教程里的那些不可能出现的情况,也就是 a.需要单独翻转一个注意,我这里说的一个棱边就是指已经合并好的两个棱块) b.只需要交换一对棱边或者一对角块,上面第三个图显示时发生的样子(他要单独只翻转黄红一个棱边,然后还得只交换黄红和黄橙一对棱边),这通常被大家称为四阶魔方需要用两个算法处理一下,他就会变成正常的三阶魔方了,然后你就可以用学过的三阶魔方的任何方法来还原四阶 好,下面我们就来讲解四阶魔方的还原方法了。 (第一步)对好第一面的中心块 这一步最简单,你要对成左边这个样子,基本上这一步的指导方针就是,先对好一对,再对好把两对儿拼起来。请看下面的例子:魔方小站
播放 动画,你也可以 最左边的回到初始状 ,然后用播放条右边 的 和一步一步看。TL'F TU TL' 先对好一对儿黄色小块 右侧的黄色小块要转到前面来 会到 A 位置,为了要两个黄 色小块对成一对,要把前面 的黄色小块先调整到 A 旁 边。 对上第二对儿。对好黄色面上面这个例子大家关键就是学会第二步,看准了右面这个小黄块要到前面的 A 位置来,你就旋转一下前面把另 备到他旁边就对了。这个例子里小黄块是从右边转到前面去还好看一点儿,你也可能碰到小黄块要从后面转到前面,大家就得仔细点,别看错了位置就拼不上了。 有时拼一对儿的时候你要注意一下不要影响了已经对好的另一对儿,如果影响了,就让他们让开,空出一个轨道由旋转了。 以用鼠标拖拽3D动画里 个魔方,以看到魔方背面 的变化。B TU F TD2 超简单吧,这步大家就学会啦。
#include
教三阶魔方你从2分钟到20秒(1)
7L内容:从30秒到25秒的教程(OLL全集,CROSS强化) 8L内容:从25秒到20秒以内的教程(慢拧与手速) 9L内容:后言 还有的是,5L~9L的内容,都需要回复才能查看,其一,我发现小站的人其实挺多,但是绝大部分都是游客,我希望来小站观光的游客能够注册帐号,这样有益于小站的发展,并且能够增加小站的人数,高手也会增加,当作做善事,其二就是这篇教材我下的功夫很多,希望各位把帖子能让跟多有需要的人看到,你回复一个顶起来后或许新手就看见了呢~ 另外说一下,你能到魔方小站的论坛来练习,都是渴望能够成为魔方高手的人。所以,一时的艰难不算什么,希望大家能够辛勤果敢,不怕困难地学习魔方,成为高手!但是假如你已经对魔方渐渐冷淡无趣,我相信你是无法进步的。所以,不怕万人阻挡,只怕自己投降!勤奋是高手的另一个名字! 还有,对教程不明白的,可以在本帖回复,对于其他魔方知识不明白的私信我,需要经常咨询或者要问的比较多的,可以加我QQ2609047698,下面进入内容,不懂可于本帖提问。
2L内容:从2分钟到1分钟的教程: 【前言】(可跳过) 三速无法达到1分钟的魔友,多半是练习不够,并且关乎到手法以及魔方的问题,其实进入1分钟相当简单,只要你肯下功夫学习,并且加上对魔方的热情,我相信每一位魔友都可以!这一步大概需要花掉半个月左右。 【关于练习】(必读) 学习了初级玩法后,必须要加强巩固初级玩法,不然初级玩法都没法掌握,就别说进一步学习新的了,必须要练习到一下几点:1.不用错公式2.不搞乱步骤3.能够独立还原。反正就是练习10遍,一遍都没有失误,发挥出正常水平就可以了,必须要保证这一点,这是很基础的。并且每天除了学习新的内容之外,还要天天都保证30次还原的练习量,有时间可以50次,甚至100次,反正就是尽可能多练习,这样进入1分是没问题的。 【关于手法】(必读) 手法,其实就是玩魔方的时候,你手指拧的方法。大家可以看到高手拧魔方,手都非常灵活,他们手速快是一方面的原因,其次就是手法问题。手法关系到你玩魔方的手速,所以新手练习手法是很有必要的。 大家可以看看FSC(就是手指快捷方法),你也可以直
图解简单易学的两种还原魔方的常用口诀公式 前言 我们常见的魔方是3x3x3的三阶魔方,英文名Rubik's cube。是一个正6 面体,有6种颜色,由26块组成,有8个角块;12个棱块;6个中心块(和中心轴支架相连)见下图: (图1) 学习魔方首先就要搞清它的以上结构,知道角块只能和角块换位,棱块只能和棱块换位,中心块不能移动。 魔方的标准色: 国际魔方标准色为:上黄-下白,前蓝-后绿,左橙-右红。 (见图2)注:(这里以白色为底面,因为以后的教程都将以白色为底面, 为了方便教学,请都统一以白色为准)。 (图 2)
认识公式 (图3)(图4)公式说明:实际上就是以上下左右前后的英文的单词的头一个大写字母表示 (图5)
(图6) (图7)
(图8) 三阶魔方入门玩法教程(一) 步骤一、完成一层 首先要做的是区分一层和一面:很多初学者对于“一面”与“一层”缺乏清楚的认识,所以在这里特别解释一下。所谓一层,就是在完成一面(如图2的白色面)的基础上,白色面的四条边,每条边的侧面只有一种颜色,图(2). 如图(1)中心块是蓝色,则它所在面的角和棱全都是蓝色,是图(2)的反方向 图(3)和(4)则是仅仅是一面的状态,而不是一层! (1)(2) (3)(4) 注:图(2)和(4)分别是图(1)和(3)的底面状态 想完成魔方,基础是最重要的,就像建筑一样,魔方也如此,基础是最重要的。
由于上文提到过中心块的固定性,这一性质,在魔方上实质起着定位的作用,简单的说就是中心块的颜色就代表它所在的面的颜色。 一、十字(就是快速法中的CROSS ) 第一种情况如图所示: 公式为R2 第二种情况如图所示: (白色下面颜色为橙色,为方便观察,特意翻出颜色) 橙白块要移到上右的位置,现在橙白块在目标位置的下面。但其橙色片没有和橙色的中心块贴在 一起。为此我们先做D’ F’ 即把橙色粘在一起,接着 R 还原到顶层,, F 是把蓝白橙还原到正确的位置(上面的F’ 使蓝白块向左移了九十度)。 公式为D’ F’ R F 图解: 当然,架十字不只只有上面两种情况,现我们在分析下其它的一些情况吧! 如下图: 橙白块的位置己对好,但颜色反了,我就先做R2化成第二种情况,然后用还原第二种情况的 (橙色下面颜色为白色,为方便观察,特意翻出颜色)
#pragma comment(lib, "glut32.lib") #pragma comment(lib, "glu32.lib") #pragma comment(lib, "opengl32.lib") #include
} glEnd(); glBegin(GL_LINE_LOOP); //绘制原点小圆for (i = 0; i < circle_points; i++) { angle = 2*PI*i/circle_points; glVertex2f(cos(angle), sin(angle)); } glEnd(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPointSize(1); glBegin(GL_POINTS); //绘制秒针刻度 for (i = 0; i < circle_point; i++) { angle = 2*PI*i/circle_point; glVertex2f(95*cos(angle), 95*sin(angle)); } glEnd(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPointSize(5); glBegin(GL_POINTS); //绘制时针刻度 for (i = 0; i < 12; i++) { angle = 2*PI*i/12; glVertex2f(95*cos(angle), 95*sin(angle)); } glEnd(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor3f(1.f,1.f,0.f); glPushMatrix(); //绘制秒针 glRotatef(m_rotAngle, 0.0f, 0.0f, 1.0f); glTranslatef(0.0f, 10.0f, 0.0f); glBegin(GL_TRIANGLES); glVertex3f(0, -100, 0); glVertex3f(1, 0, 0); glVertex3f(-1, 0, 0); glEnd(); glPopMatrix(); //绘制分针 glColor3f(1.f,0.f,0.f); glPushMatrix();
【教程】教你从2分钟到20秒 作者:魔方世纪(魔方小站) 前言: 首先,世纪写这篇文章的时候,已经sub20,大概avg16的水平了,待在小站答疑那么久,我发现小站新手居多,高手大多潜水,所以小站经常是很多新手问一些很基础的问题,为了新手不再发一些伸手帖,我特写此帖帮助那些新手。当然,这篇教程的幅度很大,不管你是两分钟的新手还是avg25的半高手,或许都适宜阅读,我的成绩是sub20,所以这篇教程为了不误导他人也就写到sub20的部分。假如已经sub20的半高手,请勿喷此帖。 这篇文章写得都是关于三阶速拧提高速度的方法,都是我的心得,本帖可能会借鉴一些小站以及魔方吧高手的原创作品,部分会进行修改,都是为了广大魔友,望高手不吝。 卖关子是可耻的,还是立刻进入真正内容,需要的魔友可以刻意去看某一楼。 2L内容:从2分钟到1分钟的教程 3L内容:从1分钟到50秒的教程(OLL21~25与PLL1~4) 4L内容:从50秒到40秒的教程(十步CROSS的学习) 5L内容:从40秒到35秒的教程(基础F2L) 6L内容:从35秒到30秒的教程(PLL全集) 7L内容:从30秒到25秒的教程(OLL全集,CROSS强化) 8L内容:从25秒到20秒以内的教程(慢拧与手速) 9L内容:后言 还有的是,5L~9L的内容,都需要回复才能查看,其一,我发现小站的人其实挺多,但是绝大部分都是游客,我希望来小站观光的游客能够注册帐号,这样有益于小站的发展,并且能够增加小站的人数,高手也会增加,当作做善事,其二就是这篇教材我下的功夫很多,希望各位把帖子能让跟多有需要的人看到,你回复一个顶起来后或许新手就看见了呢~ 另外说一下,你能到魔方小站的论坛来练习,都是渴望能够成为魔方高手的人。所以,一时的艰难不算什么,希望大家能够辛勤果敢,不怕困难地学习魔方,成为高手!但是假如你已经对魔方渐渐冷淡无趣,我相信你是无法进步的。所以,不怕万人阻挡,只怕自己投降!勤奋是高手的另一个名字! 还有,对教程不明白的,可以在本帖回复,对于其他魔方知识不明白的私信我,需要经常咨询或者要问的比较多的,可以加我QQ2609047698,下面进入内容,不懂可于本帖提问。
O p enGL的基本程序结构 常用的程序设计语言,如C、C++、Pascal、Fortran和Java等,都支持OpenGL的开发。这里只讨论C版本下OpenGL的语法。 程序的基本结构 OpenGL程序的基本结构可分为三个部分: 第一部分是初始化部分。主要是设置一些OpenGL的状态开关,如颜色模式(RGBA或ALPHA)的选择,是否作光照处理(若有的话,还需设置光源的特性),深度检验,裁剪等等。这些状态一般都用函数glEnable(???), glDisable(???)来设置,???表示特定的状态。 第二部分设置观察坐标系下的取景模式和取景框位置大小。主要利用了三个函数: 函数void glViewport(left,top,right,bottom):设置在屏幕上的窗口大小,四个参数描述屏幕窗口四个角上的坐标(以象素表示); 函数void glOrtho(left,right,bottom,top,near,far):设置投影方式为正交投影(平行投影),其取景体积是一个各面均为矩形的六面体; 函数void gluPerspective(fovy,aspect,zNear,zFar):设置投影方式为透视投影,其取景体积是一个截头锥体。
第三部分是OpenGL的主要部分,使用OpenGL的库函数构造几何物体对象的数学描述,包括点线面的位置和拓扑关系、几何变换、光照处理等等。 以上三个部分是OpenGL程序的基本框架,即使移植到使用MFC的Windows程序中,也是如此。只是由于Windows自身有一套显示方式,需要进行一些必要的改动以协调这两种不同显示方式。 OpenGL基本函数均使用gl作为函数名的前缀,如glClearColor();实用函数则使用glu作为函数名的前缀,如gluSphere()。 OpenGL基本常量的名字以GL_开头,如GL_LINE_LOOP;实用常量的名字以GLU_开头,如GLU_FILL。一些函数如glColor* ()(定义颜色值),函数名后可以接不同的后缀以支持不同的数据类型和格式。如glColor3b(...)、glColor3d(...)、 glColor3f(...)和 glColor3bv(...)等,这几个函数在功能上是相似的,只是适用于不同的数据类型和格式,其中3表示该函数带有三个参数,b、d、f分别表示参数的类型是字节型、双精度浮点型和单精度浮点型,v则表示这些参数是以向量形式出现的。 OpenGL定义了一些特殊标识符,如GLfloat,GLvoid。它们其实就是C中的 float和void。在gl.h文件中可以看到以下定义: …… typedef float GLfloat; typedef void GLvoid; ……
(图5) (图6)
(图7) (图8)步骤一、完成一层
首先要做的是区分一层和一面:很多初学者对于“一面”与“一层”缺乏清楚的认识,所以在这里特别解释一下。所谓一层,就是在完成一面(如图2的白色面)的基础上,白色面的四条边,每条边的侧面只有一种颜色,图(2). 如图(1)中心块是蓝色,则它所在面的角和棱全都是蓝色,是图(2)的反方向 图(3)和(4)则是仅仅是一面的状态,而不是一层! (1)(2) (3)(4) 注:图(2)和(4)分别是图(1)和(3)的底面状态 想完成魔方,基础是最重要的,就像建筑一样,魔方也如此,基础是最重要的。 由于上文提到过中心块的固定性,这一性质,在魔方上实质起着定位的作用,简单的说就是中心块的颜色就代表它所在的面的颜色。 一、十字(就是快速法中的CROSS) 第一种情况如图所示: (橙色下面颜色为白色,为方便观察,特意翻出颜色) 公式为R2
第二种情况如图所示: (白色下面颜色为橙色,为方便观察,特意翻出颜色) 橙白块要移到上右的位置,现在橙白块在目标位置的下面。但其橙色片没有和橙色的中心块贴在 一起。为此我们先做D’F’即把橙色粘在一起,接着 R 还原到顶层,,F 是把蓝白橙还原到正确的位置(上面的F’使蓝白块向左移了九十度)。公式为D F’R F 图解: 当然,架十字不只只有上面两种情况,现我们在分析下其它的一些情况吧! 如下图: 橙白块的位置己对好,但颜色反了,我就先做R2化成第二种情况,然后用还原第二种情况的公式即可!
上面两种情况都为前右的块要移到上后的位置。我们先做R’D’移到前下的位置, 再做R “把橙白还原上去”,接着做D2 移到后下的位置。上面两种情况分别化为上面第一 种和第二种情况。其对称情况亦是按类似上面的思想来还原!如果刚开始时橙白块也还没对好,直接做R’ D 移到后下位置即可! 二、第一层角 依然把十字放在顶层,还原角块时,我们首先在底层找有没有我们要还原的角,没有的话再到顶层去找!基本的两种情况为: 公式:D R’D’R公式:D’FDF’ 图解: 公式:D R’D’R 公式:D’FDF’
首先,说明三阶移棱魔方的十字是这个样子的。 第一步,用三阶魔方的层先法第一步,底面十字。(参考魔方小站三阶教程,自己举一反三)要注意的是,因为楞的顺序被调换了,所以十字与第二层的色块不一定方向重合,不必担心。第二步,对第二层的中心色块。 情况1: 情况1的公式就是FLFL’F’ 情况2 情况2的公式是F’R’F’RF 情况3: 情况3的公式是FLF2L’F’ 第三步,调整底层角块顺序(这一部中黑色块代表底面,灰色代表任意,白色为同色) 情况1: 如何让①块变到②块的地方,公式如下RU’R’ 情况2 ①到②公式如下:L’UL 情况3(不是在右边的话,把魔方整体往右转一下) ①到②公式如下URU’R’F’U’FU2RU’R’ 第三步:复原第二层
熟悉三阶二层公式的人就不用看这一步了,自己捉摸吧。 情况1 ①到②公式如下U’L’ULUFU’F’ 情况2 ①到②公式如下URU’R’U’F’UF 第四步:顶层十字(可参考魔方小站三阶教程)(此步所有公式正面为顶面(黑))。 情况1 情况1公式:RFUF'U'R' 情况2 情况2公式LDFD’F’L’
情况3 先做一遍情况2的公式,就会变成情况1,再摆正位置用情况1的公式。情况4 已经十字了,不用说了 特殊情况有一个或三个五边形向上(不在前四种情况的就是特殊) 公式:FRF'R'F'D'FDF'RF'R'F'D'FD 做完后就会变成前四种中的一种了 第五步:恢复顶面(本步同样公式中正面为顶面) 基本型: 基1(即魔方小站中说的“小鱼1”): 基1公式R’F’RF’R’F2R 基2(即魔方小站中说的“小鱼2”):
wp.h #include
三阶魔方玩法与口诀 目录 一、前言_________________________________________________________ - 2 - 二、认识公式_____________________________________________________ - 2 - 三、拧魔方的步骤与口诀___________________________________________ - 4 -步骤一、完成一层_____________________________________________ - 4 -(一)完成第一层十字_______________________________________ - 4 -(二)完成第一层角块_______________________________________ - 5 -步骤二、完成第二层___________________________________________ - 7 -步骤三、完成顶层_____________________________________________ - 8 -(一)顶层十字_____________________________________________ - 8 -(二)顶层平面____________________________________________ - 10 -(三)顶层角块____________________________________________ - 11 -(四)顶层棱块____________________________________________ - 12 -
OpenGL入门教程 1.第一课: 说起编程作图,大概还有很多人想起TC的#include
下图是本教程介绍的三阶魔方入门的玩法(层先法)复原的基本步骤示意图: 第一步:底棱归位(又称底部架十字,底层四个棱块正确复原的过程) 图1 魔方底层架十字可以无师自通,只是我们这一步要复原的四个棱块的相对位置顺序要注意,由于我们以白色中心 块做底层,按照我们现在的主流魔方的贴纸的帖法(上黄下白,前蓝后緑,左橙右红),如果我们先复原了白蓝 这个棱块,那我们在保持白色中心块在底部的情况下,白红的棱块就一点要放在白蓝棱块的右边,白橙棱块放在 白蓝棱块的左边,白緑棱块放在白蓝棱块的对面,由于魔方的中心块不会发生变化,所以在复原的过程中,我们 是以中心块为参照物的,第一步我们在复原白蓝、白红、白绿、白橙这四个棱块的时候,我们可以先把白色面旋 转到顶层,和黄色中心块同一个平面,然后再把他对应的另一个颜色(蓝或红或緑或橙)经过旋转最上层,使之 和对应的中心块的颜色同色,这样我们再旋转180度,对应的棱块就正确复原到底部了。 注意:图101的情况是没有正确归位的情况,需要调整白蓝和白红两个棱块的位置,才是正确的完成了底棱归位 图 101 图2 魔方的四个底角正确归位以后一定会出现倒T字型,如图2所示,如果不是这样肯定是底面角块没有正确归位(位置错了,重新来过)。 底角归位也可无师自通,有兴致的朋友可以自己琢磨一些技巧和完成这一步。有难度的朋友可参考我下面介绍的一种技巧来完成,我们先看图2-1和图2-2,首先我们先确定目标块的位置是在他要正确归位的正上面的位置,然后我们再看白色的面朝向何方,就很快的能快速判断出来是下图几种情况中的哪一种了。 复原基本思想:先将目标角块调至顶层侧面,再转动能与之相连形成顺色整体的面,使目标角与底棱连成一个(1×1×2)的归位整体,再转至正确的位置。因此,下列的五个实例并没有必要当成公式来死记。 图2-1 图2-2 图201 图202 图203
三阶魔方玩法与口诀 目录 一、前言_________________________________________________ - 3 - 二、认识公式 _____________________________________________ - 4 - 三、拧魔方的步骤与口诀 ___________________________________ - 6 - 步骤一、完成一层_______________________________________ - 6 - (一)完成第一层十字________________________________ - 6 - (二)完成第一层角块________________________________ - 7 - 步骤二、完成第二层_____________________________________ - 8 - 步骤三、完成顶层______________________________________ - 10 - (一)顶层十字_____________________________________ - 10 - (二)顶层平面_____________________________________ - 11 - (三)顶层角块_____________________________________ - 12 - (四)顶层棱块_____________________________________ - 13 - 一、前言 魔方是3x3x3的三阶魔方,英文名Rubik's cube。是一个正 6 面体,有6种颜色,由26块组成,有8个角块;12个棱块;6个中心块(和
魔方入门教程 在教程的最下面有DIY魔方的贴纸的搭配的说明 (第一步)在第一面做一个十字,形成如下的样子: 这一步可以自己试着自己琢磨去做,自己玩远比看教程有意 思的多,我在这里就先称这个十字是一个“标准十字”架好十 字后,自己再试着把顶层的一层的其它的四个角块自己补好, 补好后就算是做好了第一层,即下面的图形: 在这里我给大家解释一下在魔方的教程里:U D R L F B 字母代表的意义,一个魔方拿到手上后,如果上下看,它 的最上面的一层是Up “上”简称为U,它的最下面的一层是Down “下”简称为D。如果左右看,它的最右面的一层是Right “右”简称 为R,它的最左面的一层是Left “左”简称为L。如果前后看的 话 ,它的最前面的一层 是Front “右”简称为F,它的最后面的一层是Back “左”简称为B。
以上面的表里的标记为例,F就代表前面顺时针转90°,F'代表前面逆时针转90°,R2代表右面转180°,就这么简单,大家明白了吧。 下面有详解的图解说明:
(关于复原第一层,也可以参考下面的魔方超级入门教程)(第二步)放第二层的棱色块,形成如下的样子:
由上一步到这一步的图,大家肯定看出了这步我们要处理的是中间层红白,红黄,橙白,橙黄四个棱色块。这次,你先把魔方翻过来了,蓝面朝下,绿面朝上,再看看以上4个棱色块哪些位于顶面(绿色为中心的面),随便选择一个,我们就从它开始,这里以红白为例,通常,你会碰到两种情况, 我们要把顶面上的红白色块插入到红色箭头所示的地方, 对于第一种情况,你可以, 整个算法是URU'R' + U'F'UF,是不是很有规律?我们看,好像后一半 U'F'UF正好是前一半URU'R'的对角线镜像吧,是吧?我们看前四步 URU'R'的作用是把左图里我们要的两个小块组合起来,上表中标为红色的 第5图显示了组合好的两个色块,而后四步U'F'UF则是把我们组合好的 两个小块填近正确的位置。 所以,如果你碰见:
1、魔方常见公式符号说明(重要) 顺时针90度逆时针90度顺时针180度逆时针180度 前层 F(front) 后层 B(back) 右层 R(right) 上层 U(up) 2-1、第一种情况2-2、第二种情况 图2-1 图2-2 公式2-1:(R U R')记忆技巧:白色朝右,第一步就旋转右层公式2-2:(F'U'F)记忆技巧:白色朝前,第一步就旋转前层 2-3、第三种情况 图2-3 用两次公式2-1 (R U R')U' (R U R') 2-4、第四种情况 图2-4 用两次公式2-2 (F'U'F)U(F'U'F) 2-5、第五种情况 图2-5 用三次公式2-1 (R U R')(R U R')U' (R U R')= (R U U R')U' (R U R') 第三步:中棱归位(复原魔方中层四个棱块的步骤) 3-1、第一种情况 图3-1 公式3-1:(U' F' U F )(U R U' R') 3-2、第二种情况 图3-2 公式3-2 :(U R U' R')(U' F' U F) 2、魔方最流行的配色 上黄-下白 前蓝-后绿 左橙-右红 第二步:底角归位(复 原魔方第一层四个角 块) 3、魔方还原方法: 第一步:底棱归位(又 称底部架十字,底层 四个棱块正确复原的 过程) 魔方底层架十字可以无师自通,只是我们这一步要复原的四 个棱块的相对位置顺序要注意,由于我们以白色中心块做底层, 按照现在的主流魔方的贴纸的帖法(上黄下白,前蓝后緑,左橙 右红),如果我们先复原了白蓝这个棱块,那我们在保持白色中心 块在底部的情况下,白红的棱块就一点要放在白蓝棱块的右边, 白橙棱块放在白蓝棱块的左边,白緑棱块放在白蓝棱块的对面, 由于魔方的中心块不会发生变化,所以在复原的过程中,我们是 以中心块为参照物的,第一步我们在复原白蓝、白红、白绿、白 橙这四个棱块的时候,我们可以先把白色面旋转到顶层,和黄色 中心块同一个平面,然后再把他对应的另一个颜色(蓝或红或緑 或橙)经过旋转最上层,使之和对应的中心块的颜色同色,这样 我们再旋转180度,对应的棱块就正确复原到底部了。
(第一步)在第一面做一个十字,形成如下的样子: 注意啊,你对好的十字必须如上图,每个侧面的棱和中心是同色的。做成这步的方法很多,我建议你自由发挥。如果实在有困难,我这里提供一个万全的办法,就是把中间层含有蓝色的棱色块变到底面上去,然后对好侧面颜色,再翻上来。我这里就举一个例子大家就应该明白了,对于左图B 位置,只需要下面3步,魔方 D 我说的够清楚了吧。而对于A和C位置你可以旋转该面,让其变到B或D位置。如果某个棱色块的蓝色面已经在顶面或底面,相信大家会
有办法解决的。你要记住的是,如果遇到困难,就把蓝色变到底面,在底面上你是可以任意旋转的。 有时候,你会碰到这样的情况,蓝黄色块转到底面时影响了已经对好的红色面,这时候,你需要在最后一步之前恢复红色面的位置。具体操作见下。 魔方小站) D F' R2 照上面说的,你重复做4个棱,应该就可以做好十字啦。
这里我给初学者建议一种更清晰快速的方法,蓝色棱变到底面之后,可以不急着把它翻上去,可以变成左图这个样子,注意在底面上4个棱可以是任意顺序,这会给你减少很大难度,这里是两个例子,给大家开阔下思路, 最后把他们逐一对好侧面颜色翻上去就行啦。比如: 下面我要说说标记。你没准注意到上个表格里的一些奇怪的字母,那些字母的意思很简单, 以上面的表里的标记为例,F就代表前面顺时针转90°,F'代表前面逆时针转90°,R2代表右面转180°,就这么简单,大家明白了吧。 (第二步)对好第一面,但是留下一个角,形成: 具体留下哪个角,你自己决定,做好这一步其实你只要学会一招就够了。那个蓝色的角色块,转来转去之后就6种位置,
三阶魔方入门教程 前言 我们常见的魔方是3x3x3的三阶魔方,是一个正6 面体,有6种颜色,由26块组成,有8个角块;12个棱块;6个中心块(和中心轴支架相连)见下图: (图1) 学习魔方首先就要搞清它的以上结构,知道角块只能和角块换位,棱块只能和棱块换位,中心块不能移动。 魔方的标准色: 国际魔方标准色为:上黄-下白,前蓝-后绿,左橙-右红。(见图2)注:(这里以白色为底面,因为以后的教程都将以白色为底面,为了方便教学,请都统一以白色为准)。 (图2) 认识公式 (图3)(图4) 公式说明:实际上就是以上下左右前后的英文的单词的头一个大写字母表示
(图5) (图6)
(图7) (图8)
步骤一、完成一层 首先要做的是区分一层和一面:很多初学者对于“一面”与“一层”缺乏清楚的认识,所以在这里特别解释一 下。所谓一层,就是在完成一面(如图2的白色面)的基础上,白色面的四条边,每条边的侧面只有一种颜色,图(2). 如图(1)中心块是蓝色,则它所在面的角和棱全都是蓝色,是图(2)的反方向 图(3)和(4)则是仅仅是一面的状态,而不是一层 ! (1) (2) (3) (4) 注:图(2)和(4)分别是图(1)和(3)的底面状态 想完成魔方,基础是最重要的,就像建筑一样,魔方也如此,基础是最重要的。 由于上文提到过中心块的固定性,这一性质,在魔方上实质起着定位的作用,简单的说就是中心块的颜色就代表它所在的面的颜色。 一、十字(就是快速法中的CROSS ) 第一种情况如图所示: 公式为R2 第二种情况如图所示: (白色下面颜色为橙色,为方便观察,特意翻出颜色) 橙白块要移到上右的位置,现在橙白块在目标位置的下面。但其橙色片没有和橙色的中心块贴在 (橙色下面颜色为白色,为方便观察,特意翻出颜色)