NeHe OpenGL教程 第三十七課:卡通映射

轉自【翻譯】NeHe OpenGL 教程

前言

聲明,此?NeHe OpenGL教程系列文章由51博客yarin翻譯(2010-08-19),本博客為轉載并稍加整理與修改。對NeHe的OpenGL管線教程的編寫,以及yarn的翻譯整理表示感謝。

?

NeHe OpenGL第三十七課:卡通映射

卡通映射:

什么是卡通了,一個輪廓加上少量的幾種顏色。使用一維紋理映射,你也可以實現這種效果。
?
看到人們仍然e-mail我請求在文章中使用我方才在GameDev.net上寫的源代碼,還看到文章的第二版(在那每一個API附帶源碼)不是在中途完成之前連貫的結束。我已經把這篇指南一并出租給了NeHe(這實際上是

寫文章的最初意圖)因此你們所有的OpenGL領袖可以玩轉它。對模型的選擇表示抱歉,但是我最近一直在玩Quake 2。
注釋:這篇文章的源代碼可以在這里找到:
http://www.gamedev.net/reference/programming/features/celshading.
這篇指南實際上并不解釋原理,僅僅解釋代碼。在上面的連接中可以發現為什么它能工作。現在不斷地大聲抱怨STOP E-MAILING ME REQUESTS FOR SOURCE CODE!!!!
首先,我們需要包含一些額外的頭文件。第一個(math.h)我們可以使用sqrtf (square root)函數,第二個用來訪問文件。

#include <math.h>??????
#include <stdio.h>??????

現在我們將定義一些結構體來幫助我們存貯我們的數據(保存好幾百浮點數組)。第一個是tagMATRIX結構體。如果你仔細地看,你將看到我們正象包含一個十六個浮點數的1維數組~一個2維4×4數族一樣存儲那個矩陣

。這下至OpenGL存儲它的矩陣的方式。如果我們使用4x4數組,這些值將發生錯誤的順序。
?
typedef struct tagMATRIX?????// 保存OpenGL矩陣的結構體
{
?float Data[16];?????// 由于OpenGL的矩陣的格式我們使用[16
}
MATRIX;

第二是向量的類。 僅存儲X,Y和Z的值?
??
typedef struct tagVECTOR?????// 存儲一個單精度向量的結構體
{
?float X, Y, Z;?????// 向量的分量
}
VECTOR;

第三,我們持有頂點的結構。每一個頂點僅需要它的法線和位置(沒有紋理的現行縱坐標)信息。它們必須以這樣的次序被存放,否則當它停止裝載文件的事件將發生嚴重的錯誤(我發現艱難的情形:(教我分塊出租我

的代碼。)。
?
typedef struct tagVERTEX?????// 存放單一頂點的結構
{
?VECTOR Nor;?????// 頂點法線
?VECTOR Pos;?????// 頂點位置
}
VERTEX;

最后是多邊形的結構。我知道這是存儲頂點的愚蠢的方法,要不是它完美工作的簡單的緣故。通常我愿意使用一個頂點數組,一個多邊形數組,和包括一個在多邊形中的3個頂點的指數,但這比較容易顯示你想干什么。?
??
typedef struct tagPOLYGON?????// 存儲單一多邊形的結構
{
?VERTEX Verts[3];?????// 3個頂點結構數組
}
POLYGON;

優美簡單的材料也在這里了。為每一個變量的一個解釋考慮那個注釋。?
??
bool??outlineDraw?= true;????// 繪制輪廓的標記
bool??outlineSmooth?= false;????// Anti-Alias 線段的標記
float??outlineColor[3]?= { 0.0f, 0.0f, 0.0f };??// 線段的顏色
float??outlineWidth?= 3.0f;????// 線段的寬度

VECTOR??lightAngle;?????// 燈光的方向
bool??lightRotate?= false;????// 是否我們旋轉燈光的標記

float??modelAngle?= 0.0f;????// 模型的Y軸角度
bool??? ?modelRotate?= false;?????// 旋轉模型的標記

POLYGON??*polyData?= NULL;?????// 多邊形數據
int??polyNum??= 0;????// 多邊形的編號

GLuint??shaderTexture[1];?????// 存儲紋理ID

這是得到的再簡單不過的模型文件格式。 最初的少量字節存儲在場景中的多邊形的編號,文件的其余是tagPOLYGON結構體的一個數組。正因如此,數據在沒有任何需要去分類到詳細的順序的情況下被讀出。?
??
BOOL ReadMesh ()??????// 讀“model.txt” 文件
{
?FILE *In = fopen ("Data\\model.txt", "rb");??// 打開文件

?if (!In)
??return FALSE;????// 如果文件沒有打開返回 FALSE

?fread (&polyNum, sizeof (int), 1, In);??// 讀文件頭,多邊形的個數

?polyData = new POLYGON [polyNum];???// 分配內存

?fread (&polyData[0], sizeof (POLYGON) * polyNum, 1, In);// 把所有多邊形的數據讀入

?fclose (In);?????// 關閉文件

?return TRUE;?????// 工作完成
}

一些基本的數學函數而已。DotProduct計算2個向量或平面之間的角,Magnitude函數計算向量的長度,Normalize函數縮放向量到一個單位長度。
?
inline float DotProduct (VECTOR &V1, VECTOR &V2)??//計算兩個向量之間的角度
{
?return V1.X * V2.X + V1.Y * V2.Y + V1.Z * V2.Z;??
}

inline float Magnitude (VECTOR &V)????// 計算向量的長度
{
?return sqrtf (V.X * V.X + V.Y * V.Y + V.Z * V.Z);?
}

void Normalize (VECTOR &V)?????// 創建一個單位長度的向量
{
?float M = Magnitude (V);????

?if (M != 0.0f)?????// 確保我們沒有被0隔開
?{
??V.X /= M;?????
??V.Y /= M;
??V.Z /= M;
?}
}

這個函數利用給定的矩陣旋轉一個向量。請注意它僅旋轉這個向量——與向量的位置相比它算不了什么。它用來當旋轉法線確保當我們在計算燈光時它們停留在正確的方向上。?
??
void RotateVector (MATRIX &M, VECTOR &V, VECTOR &D)??// 利用提供的矩陣旋轉一個向量
{
?D.X = (M.Data[0] * V.X) + (M.Data[4] * V.Y) + (M.Data[8]? * V.Z);?
?D.Y = (M.Data[1] * V.X) + (M.Data[5] * V.Y) + (M.Data[9]? * V.Z);?
?D.Z = (M.Data[2] * V.X) + (M.Data[6] * V.Y) + (M.Data[10] * V.Z);?
}

引擎的第一個主要的函數…… 初始化,按所說的精確地做。我已經砍掉了在注釋中不再需要的代碼段。?
??
// 一些GL 初始代碼和用戶初始化從這里開始
BOOL Initialize (GL_Window* window, Keys* keys)
{

這3個變量用來裝載著色文件。在文本文件中為了單一的線段線段包含了空間,雖然shaderData存儲了真實的著色值。你可能奇怪為什么我們的96個值被32個代替了。好了,我們需要轉換greyscale 值為RGB以便

OpenGL能使用它們。我們仍然可以以greyscale存儲這些值,但向上負載紋理時我們至于R,G和B成分僅僅使用同一值。?
??
?char Line[255];??????// 255個字符的存儲量
?float shaderData[32][3];?????// 96個著色值的存儲量
?g_window?= window;?g_keys??= keys;
?FILE *In = NULL;??????// 文件指針

當繪制線條時,我們想要確保很平滑。初值被關閉,但是按“2”鍵,它可以被toggled on/off。?
??
?glShadeModel (GL_SMOOTH);????// 使用色彩陰影平滑
?glDisable (GL_LINE_SMOOTH);????// 線條平滑初始化不可用

?glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);?// 提高計算精度??
?glClearColor (0.7f, 0.7f, 0.7f, 0.0f);??// 設置為灰色背景?
?glClearDepth (1.0f);????// 設置深度緩存值
? ?glEnable (GL_DEPTH_TEST); ?// 啟用深度測試
? ?glDepthFunc (GL_LESS); ?// 設置深度比較函數
?glShadeModel (GL_SMOOTH); ?// 啟用反走樣
? ?glDisable (GL_LINE_SMOOTH);

glEnable (GL_CULL_FACE);????// 啟用剔除多邊形功能

我們使 OpenGL燈光不可用因為我們自己做所以的燈光計算。?

?glDisable (GL_LIGHTING);????// 使 OpenGL 燈光不可用

這里是我們裝載陰影文件的地方。它簡單地以32個浮點值ASCII碼存放(為了輕松修改),每一個在separate線上。?

?In = fopen ("Data\\shader.txt", "r");???// 打開陰影文件

?if (In)???????// 檢查文件是否打開
?{
??for (i = 0; i < 32; i++)????// 循環32次
??{
???if (feof (In))????// 檢查文件是否結束
????break;

???fgets (Line, 255, In);???// 獲得當前線條

這里我們轉換 greyscale 值為 RGB, 正象上面所描述的。?

???// 從頭到尾復制這個值
???shaderData[i][0] = shaderData[i][1] = shaderData[i][2] = atof (Line);
??}

??fclose (In);?????// 關閉文件
?}

?else
??return FALSE;?????
??
現在我們向上裝載這個紋理。同樣它清楚地規定,不要使用任何一種過濾在紋理上否則它看起來奇怪,至少可以這樣說。GL_TEXTURE_1D被使用因為它是值的一維數組。?

?glGenTextures (1, &shaderTexture[0]);???// 獲得一個自由的紋理ID

?glBindTexture (GL_TEXTURE_1D, shaderTexture[0]);??// 綁定這個紋理。 從現在開始它變為一維

?// 使用鄰近點過濾
?glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
?glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

?// 設置紋理
?glTexImage1D (GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGB , GL_FLOAT, shaderData);

現在調整燈光方向。我已經使得它向下指向Z軸正方向,這意味著它將正面碰撞模型?

?lightAngle.X = 0.0f;?????
?lightAngle.Y = 0.0f;?????
?lightAngle.Z = 1.0f;????

?Normalize (lightAngle);

讀取Mesh文件,并返回?
?return ReadMesh ();?????// 讀取Mesh文件,并返回
}

與上面的函數相對應…… 卸載,刪除由Initalize 和 ReadMesh 創建的紋理和多邊形數據。?
??
void Deinitialize (void)
{
?glDeleteTextures (1, &shaderTexture[0]);??// 刪除陰影紋理

?delete [] polyData;????// 刪除多邊形數據
}

主要的演示循環。所有這些用來處理輸入和更新角度。控制如下:
<SPACE> =鎖定旋轉

1 = 鎖定輪廓繪制
2 = 鎖定輪廓 anti-aliasing

<UP> =增加線寬
<DOWN> = 減小線寬
?
void Update (DWORD milliseconds)????// 這里執行動作更新
{
?if (g_keys->keyDown [' '] == TRUE)???// 空格是否被按下
?{
??modelRotate = !modelRotate;???// 鎖定模型旋轉開/關

??g_keys->keyDown [' '] = FALSE;
?}

?if (g_keys->keyDown ['1'] == TRUE)???// 1是否被按下
?{
??outlineDraw = !outlineDraw;???// 切換是否繪制輪廓線

??g_keys->keyDown ['1'] = FALSE;
?}

?if (g_keys->keyDown ['2'] == TRUE)???// 2是否被按下
?{
??outlineSmooth = !outlineSmooth;??// 切換是否使用反走樣

??g_keys->keyDown ['2'] = FALSE;
?}

?if (g_keys->keyDown [VK_UP] == TRUE)???// 上鍵增加線的寬度
?{
??outlineWidth++;?????

??g_keys->keyDown [VK_UP] = FALSE;
?}

?if (g_keys->keyDown [VK_DOWN] == TRUE)??// 下減少線的寬度
?{
??outlineWidth--;?????

??g_keys->keyDown [VK_DOWN] = FALSE;
?}

?if (modelRotate)?????// 是否旋轉
??modelAngle += (float) (milliseconds) / 10.0f;?// 更新旋轉角度
}

你一直在等待的函數。Draw 函數做每一件事情——計算陰影的值,著色網孔,著色輪廓,等等,這是它作的。?
??
void Draw (void)
{

TmpShade用來存儲當前頂點的色度值。所有頂點數據同時被計算,意味著我們只需使用我們能繼續使用的單個的變量。
TmpMatrix, TmpVector 和 TmpNormal同樣被用來計算頂點數據,TmpMatrix在函數開始時被調整一次并一直保持到Draw函數被再次調用。TmpVector 和 TmpNormal則相反,當另一個頂點被處理時改變。

?float TmpShade;??????// 臨時色度值

?MATRIX TmpMatrix;??????// 臨時 MATRIX 結構體
?VECTOR TmpVector, TmpNormal;????// 臨時 VECTOR結構體

清除緩沖區矩陣數據?

?glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);?//? 清除緩沖區
?glLoadIdentity ();?????// 重置矩陣

首先檢查我們是否想擁有平滑的輪廓。如果是,我們就打開anti-alaising 。否則把它關閉。簡單!?

?if (outlineSmooth)?????// 檢查我們是否想要 Anti-Aliased 線條
?{
??glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);?// 啟用它們
??glEnable (GL_LINE_SMOOTH);???
?}

?else??????// 否則不啟用
??glDisable (GL_LINE_SMOOTH);??
??
然后我們設置視口。我們反向移動攝象機2個單元,之后以一定角度旋轉模型。注:由于我們首先移動攝象機,這個模型將在現場旋轉。如果我們以另一種方法做,模型將繞攝象機旋轉。
我們之后從OpenGL中取最新創建的矩陣并把它存儲在 TmpMatrix。

?glTranslatef (0.0f, 0.0f, -2.0f);???// 移入屏幕兩個單位
?glRotatef (modelAngle, 0.0f, 1.0f, 0.0f);??// 繞Y軸旋轉這個模型

?glGetFloatv (GL_MODELVIEW_MATRIX, TmpMatrix.Data);?// 獲得產生的矩陣

戲法開始了。首先我們啟用一維紋理,然后啟用著色紋理。這被OpenGL用來當作一個look-up表格。我們之后調整模型的顏色(白色)我選擇白色是因為它亮度高并且描影法比其它顏色好。我建議你不要使用黑色:)

?// 卡通渲染代碼
?glEnable (GL_TEXTURE_1D);????// 啟用一維紋理
?glBindTexture (GL_TEXTURE_1D, shaderTexture[0]);?// 鎖定我們的紋理

?glColor3f (1.0f, 1.0f, 1.0f);????// 調整模型的顏色

現在我們開始繪制那些三角形。盡管我們看到在數組中的每一個多邊形,然后旋轉它的每一個頂點。第一步是拷貝法線信息到一個臨時的結構中。因此我們能旋轉法線,但仍然保留原來保存的值(沒有精確降級)。

?glBegin (GL_TRIANGLES);?????// 告訴 OpenGL 我們即將繪制三角形

??for (i = 0; i < polyNum; i++)???// 從頭到尾循環每一個多邊形
??{
???for (j = 0; j < 3; j++)???// 從頭到尾循環每一個頂點
???{
????TmpNormal.X = polyData[i].Verts[j].Nor.X;?// 用當前頂點的法線值填充TmpNormal結構
????TmpNormal.Y = polyData[i].Verts[j].Nor.Y;?
????TmpNormal.Z = polyData[i].Verts[j].Nor.Z;

第二,我們通過初期從OpenGL中攫取的矩陣來旋轉這個法線。我們之后規格化因此它并不全部變為螺旋形。?

????// 通過矩陣旋轉
????RotateVector (TmpMatrix, TmpNormal, TmpVector);

????Normalize (TmpVector);??// 規格化這個新法線

第三,我們獲得那個旋轉的法線的點積燈光方向(稱為lightAngle,因為我忘了從我的舊的light類中改變它)。我們之后約束這個值在0——1的范圍。(從-1到+1)

????// 計算色度值
????TmpShade = DotProduct (TmpVector, lightAngle);

????if (TmpShade < 0.0f)
?????TmpShade = 0.0f;?// 如果負值約束這個值到0

第四,對于OpenGL我們象忽略紋理坐標一樣忽略這個值。陰影紋理與一個查找表一樣來表現(色度值正成為指數),這是(我認為)為什么1D紋理被創造主要原因。對于OpenGL我們之后忽略這個頂點位置,并不斷重

復,重復。至此我認為你已經抓到了概念。?

????glTexCoord1f (TmpShade);?// 規定紋理的縱坐標當作這個色度值
????// 送頂點
????glVertex3fv (&polyData[i].Verts[j].Pos.X);
????? }
??}

?glEnd ();??????// 告訴OpenGL 完成繪制

?glDisable (GL_TEXTURE_1D);????// 1D 紋理不可用

現在我們轉移到輪廓之上。一個輪廓能以“它的相鄰的邊,一邊為可見,另一邊為不可見”定義。在OpenGL中,這是深度測試被規定小于或等于(GL_LEQUAL)當前值的地方,并且就在那時所有前面的面被精選。我們同

樣也要混合線條,以使它看起來不錯:)
那么,我們使混合可用并規定混合模式。我們告訴OpenGL與著色線條一樣著色backfacing多邊形,并且規定這些線條的寬度。我們精選所有前面多邊形,并規定測試深度小于或等于當前的Z值。在這個線條的的顏色被

規定后,我們從頭到尾循環每一個多邊形,繪制它的頂點。我們僅需忽略頂點位置,而不是法線或著色值因為我們需要的僅僅是輪廓。

?// 輪廓代碼
?if (outlineDraw)??????// 檢查看是否我們需要繪制輪廓
?{
??glEnable (GL_BLEND);????// 使混合可用
??// 調整混合模式
??glBlendFunc (GL_SRC_ALPHA ,GL_ONE_MINUS_SRC_ALPHA);

??glPolygonMode (GL_BACK, GL_LINE);???// 繪制輪廓線
??glLineWidth (outlineWidth);????// 調整線寬

??glCullFace (GL_FRONT);????// 剔出前面的多邊形

??glDepthFunc (GL_LEQUAL);????// 改變深度模式

??glColor3fv (&outlineColor[0]);???// 規定輪廓顏色

??glBegin (GL_TRIANGLES);????// 告訴OpenGL我們想要繪制什么

???for (i = 0; i < polyNum; i++)??// 從頭到尾循環每一個多邊形
???{
????for (j = 0; j < 3; j++)??// 從頭到尾循環每一個頂點
????{
?????// 送頂點
?????glVertex3fv (&polyData[i].Verts[j].Pos.X);
????}
???}

??glEnd ();??????// 告訴 OpenGL我們已經完成

這樣以后,我們就把它規定為以前的狀態,然后退出?

??glDepthFunc (GL_LESS);????// 重置深度測試模式

??glCullFace (GL_BACK);????// 重置剔出背面多邊形

??glPolygonMode (GL_BACK, GL_FILL);???// 重置背面多邊形繪制方式

??glDisable (GL_BLEND);????//? 混合不可用
?}
}
原文及其個版本源代碼下載:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=37

轉載于:https://www.cnblogs.com/arxive/p/6239540.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394267.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394267.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394267.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SDN交換機在云計算網絡中的應用場景

SDN的技術已經發展了好幾年了&#xff0c;而云計算的歷史更長&#xff0c;兩者的結合更是作為SDN的一個殺手級應用在近兩年炒得火熱&#xff0c;一些知名咨詢公司的關于SDN逐年增加的市場份額的論斷&#xff0c;也主要是指SDN在云計算網絡中的應用。 關于SDN在云計算網絡中的應…

sql server 里面怎么支持數字使用雙引號_國查:用中文編寫SQL

這兩天被 文言(wenyan-lang)刷屏了&#xff0c;這個項目在于使用文言文進行編程&#xff0c;我打算蹭個熱度&#xff0c;把年初的作品再撈一撈&#xff0c;即中文SQL。1. 文言Wenyan&#xff1a;吾有一數。曰三。名之曰「甲」。為是「甲」遍。吾有一言。曰「「問天地好在。」」…

七日掌握設計配色基礎_掌握正確的基礎知識:如何設計網站的導航,搜索和首頁...

七日掌握設計配色基礎by Anant Jain通過Anant Jain 掌握正確的基礎知識&#xff1a;如何設計網站的導航&#xff0c;搜索和首頁 (Get the basics right: how to design your site’s navigation, search, and homepage) 一個7分鐘的指南&#xff0c;使這三個基礎組件正確無誤。…

python渲染光線_python模板渲染配置文件

python的mako、jinja2模板庫&#xff0c;確實好用&#xff01;這里做個筆記&#xff0c;好記性不如爛筆頭。#!/usr/bin/env python#encodingutf-8import sys,yaml # 配置文件使用yaml格式from mako.template import Template # 加載mako庫的Templat…

leetcode114. 二叉樹展開為鏈表(深度優先搜索)

給定一個二叉樹&#xff0c;原地將它展開為一個單鏈表。例如&#xff0c;給定二叉樹1/ \2 5/ \ \ 3 4 6 將其展開為&#xff1a;1\2\3\4\5\6代碼 class Solution {public void flatten(TreeNode root) {flat(root);}public TreeNode flat(TreeNode root) {if(rootnull)…

eclipse新建web項目

需要點擊File—>New—>Other…在Web文件夾下找到Dynamic Web Project—>Next修改server端口可以在啟動項目后訪問地址是端口號項目名轉載于:https://juejin.im/post/5cb4999df265da037b610545

idea tips

AltInsert 自動出現generate ,,里面有構造方法&#xff0c;getter,setter... CtrlO,重寫方法 CtrlI...自動出現接口的方法 轉載于:https://www.cnblogs.com/bin-lin/p/6247538.html

革新以太網交換機架構 全光網絡的風刮進園區

全光網絡的風正在刮進園區網&#xff0c;眾所周知&#xff0c;光纖入戶發展迅速&#xff0c;隨著PON&#xff08;無源光纖網絡&#xff09;技術在運營商通信網絡的大規模使用&#xff0c;PON相關產業鏈逐步成熟&#xff0c;這也使得PON技術逐步在企業園區網得到應用。 基于銅線…

mysql loop循環實例_MySql CURSOR+LOOP循環-使用小實例

轉載自https://blog.csdn.net/starinbrook/article/details/77078126轉載自https://blog.csdn.net/makang456/article/details/53896346/【簡介】游標實際上是一種能從包括多條數據記錄的結果集中每次提取一條記錄的機制。游標充當指針的作用。盡管游標能遍歷結果中的所有行&am…

react數據從本地讀取_如何將從Google表格讀取的React應用程序部署到Netlify

react數據從本地讀取In this tutorial, we’re going to cover how to connect to a spreadsheet hosted on Google, display that information inside a React application, and deploy it to Netlify.在本教程中&#xff0c;我們將介紹如何連接到Google托管的電子表格&#x…

leetcode743. 網絡延遲時間(迪杰斯特拉算法)

有 N 個網絡節點&#xff0c;標記為 1 到 N。 給定一個列表 times&#xff0c;表示信號經過有向邊的傳遞時間。 times[i] (u, v, w)&#xff0c;其中 u 是源節點&#xff0c;v 是目標節點&#xff0c; w 是一個信號從源節點傳遞到目標節點的時間。 現在&#xff0c;我們從某個…

在線python視頻教程_【好程序員】2019 Python全套視頻教程2

2019千鋒好程序員全新Python教程&#xff0c;深入淺出的講解Python語言的基礎語法&#xff0c;注重基本編程能力訓練&#xff0c;深入解析面向對象思想&#xff0c;數據類型和變量、運算符、流程控制、函數、面向對象、模塊和包、生成器和迭代器。教程列表&#xff1a;千鋒Pyth…

洛谷——P1546 最短網絡 Agri-Net

P1546 最短網絡 Agri-Net 題目背景 農民約翰被選為他們鎮的鎮長&#xff01;他其中一個競選承諾就是在鎮上建立起互聯網&#xff0c;并連接到所有的農場。當然&#xff0c;他需要你的幫助。 題目描述 約翰已經給他的農場安排了一條高速的網絡線路&#xff0c;他想把這條線路共享…

漫談單點登錄(SSO)(淘寶天貓)(轉載)

1. 摘要 &#xff08; 注意&#xff1a;請仔細看下摘要&#xff0c;留心此文是否是您的菜&#xff0c;若浪費寶貴時間&#xff0c;深感歉意&#xff01;&#xff01;&#xff01;&#xff09; SSO這一概念由來已久&#xff0c;網絡上對應不同場景的成熟SSO解決方案比比皆是&…

mysql mdl 鎖_MySQL MDL鎖

MDL全稱為metadata lock&#xff0c;即元數據鎖。MDL鎖主要作用是維護表元數據的數據一致性&#xff0c;在表上有活動事務(顯式或隱式)的時候&#xff0c;不可以對元數據進行寫入操作。因此從MySQL5.5版本開始引入了MDL鎖&#xff0c;來保護表的元數據信息&#xff0c;用于解決…

Card Game Again CodeForces - 818E (雙指針)

大意: 給定序列, 求多少個區間積被k整除. 整除信息滿足單調性, 顯然雙指針. 具體實現只需要考慮k的素數向量, 對每一維維護個指針即可. 這題看了下cf其他人的做法, 發現可以直接暴力, 若當前的前綴積模k為0, 暴力向前求出第一個后綴積為0的位置即可, 復雜度是$O(n)$的并且相當好…

pacf和acf_如何通過Wordpress API,ACF和Express.js使Wordpress更加令人興奮

pacf和acfby Tyler Jackson泰勒杰克遜(Tyler Jackson) 如何通過Wordpress API&#xff0c;ACF和Express.js使Wordpress更加令人興奮 (How to make Wordpress more exciting with the Wordpress API, ACF, & Express.js) I’ve been working with Wordpress since it’s pr…

python運行出現數據錯誤_Python運行出錯情況

1、錯誤內容&#xff1a;You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory str). It is highly recommended that you instead just switch your application to Unicode strings.錯誤描述&#x…

leetcode95. 不同的二叉搜索樹 II(遞歸)

給定一個整數 n&#xff0c;生成所有由 1 ... n 為節點所組成的 二叉搜索樹 。示例&#xff1a;輸入&#xff1a;3 輸出&#xff1a; [[1,null,3,2],[3,2,null,1],[3,1,null,null,2],[2,1,3],[1,null,2,null,3] ] 解釋&#xff1a; 以上的輸出對應以下 5 種不同結構的二叉搜索樹…

數據結構探險系列—棧篇-學習筆記

數據結構探險—棧篇 什么是棧&#xff1f; 古代棧就是牲口棚的意思。 棧是一種機制&#xff1a;后進先出 LIFO&#xff08;last in first out&#xff09; 電梯 棧要素空棧。棧底&#xff0c;棧頂。沒有元素的時候&#xff0c;棧頂和棧底指向同一個元素&#xff0c;如果加入新元…