PSP पर 3 डी ग्राफिक्स प्रदर्शित करें

कुछ महीने पहले, मैंने फिर से एक बॉक्स से एक डस्टी पीएसपी निकाला और वहां मेरे पहले दिखाए गए इंजन को पोर्ट करने का फैसला किया। सॉफ़्टवेयर रेंडरिंग में कोई समस्या नहीं थी - सब कुछ इस तरह से काम करता है। लेकिन GU का उपयोग करना इतना सरल नहीं था। इस अनुच्छेद में, मैं आपको एक उदाहरण दिखाऊंगा कि कैसे आप GU का उपयोग करते हुए PSP के लिए एक सरल त्रि-आयामी एप्लिकेशन लिख सकते हैं।

मैं आपको पहले से चेतावनी देता हूं कि पीएसपी के लिए पर्याप्त प्रोग्रामिंग गाइड नहीं हैं, और इसलिए मेरे कुछ निष्कर्ष गलत हो सकते हैं। लेकिन, मुद्दे पर।

PSP के लिए कार्यक्रम का मुख्य कार्य, यदि कोई नहीं जानता है, तो यह इस तरह दिखता है:

#include <pspkernel.h> #include <pspdebug.h> #include <pspdisplay.h> //---------------------------------------------------------------------------------------- PSP_MODULE_INFO("GUTexture", 0, 1, 1); PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER|THREAD_ATTR_VFPU); void dump_threadstatus(void); bool done=false; int exit_callback(int arg1,int arg2,void *common) { done=true; return(0); } int CallbackThread(SceSize args, void *argp) { int cbid; cbid=sceKernelCreateCallback("Exit Callback",exit_callback,NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return(0); } int SetupCallbacks(void) { int thid = 0; thid=sceKernelCreateThread("update_thread",CallbackThread,0x11,0xFA0,0,0); if(thid>=0) sceKernelStartThread(thid, 0, 0); return(thid); } //---------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------- int main(int argc, char **argv) { pspDebugScreenInit(); //  SetupCallbacks(); //  ………. //   sceKernelExitGame(); return(0); } 

जीयू की शुरूआत इस प्रकार है:

सबसे पहले, हम तीन बफ़र्स - स्क्रीन, ऑफ-स्क्रीन और डेप्थ बफर (जेड-बफर) की ओर संकेत करते हैं। बफ़र्स को 512 पिक्सेल प्रति पंक्ति (हालांकि PSP में 480 पिक्सेल की एक पंक्ति है) में संरेखित किया गया है। आपको पिक्सेल रंग प्रारूप पर भी विचार करने की आवश्यकता है। इस उदाहरण में, GU_PSM_8888 प्रारूप का उपयोग किया जाता है - पिक्सेल के रंग के 8 बिट प्रति R, G, B और अल्फा-घटक। जेड-बफर के लिए, GU_PSM_4444 प्रारूप का उपयोग केवल इसलिए किया जाता है क्योंकि यह 16 बिट्स है - पीएसपी का 16-बिट जेड-बफर।

 //  #define SCREEN_WIDTH 480 #define SCREEN_HEIGHT 272 #define SCREEN_LINE_WIDTH 512 void* fbp0=getStaticVramBuffer(SCREEN_LINE_WIDTH, SCREEN_HEIGHT,GU_PSM_8888); void* fbp1=getStaticVramBuffer(SCREEN_LINE_WIDTH, SCREEN_HEIGHT,GU_PSM_8888); void* zbp=getStaticVramBuffer(SCREEN_LINE_WIDTH, SCREEN_HEIGHT,GU_PSM_4444); 

बफ़र्स को पॉइंटर्स को क्वेरी करने के फ़ंक्शन को इस प्रकार परिभाषित किया गया है

 #include <pspge.h> #include <pspgu.h> static unsigned int staticOffset=0; static unsigned int getMemorySize(unsigned int width,unsigned int height,unsigned int psm) { switch (psm) { case GU_PSM_T4: return((width*height)>>1); case GU_PSM_T8: return(width*height); case GU_PSM_5650: case GU_PSM_5551: case GU_PSM_4444: case GU_PSM_T16: return(2*width*height); case GU_PSM_8888: case GU_PSM_T32: return(4*width*height); default: return(0); } } void* getStaticVramBuffer(unsigned int width,unsigned int height,unsigned int psm) { unsigned int memSize=getMemorySize(width,height,psm); void* result=(void*)staticOffset; staticOffset+=memSize; return(result); } void* getStaticVramTexture(unsigned int width,unsigned int height,unsigned int psm) { void* result=getStaticVramBuffer(width,height,psm); return((void*)(((unsigned int)result) + ((unsigned int)sceGeEdramGetAddr()))); } 

ये मेरे कार्य नहीं हैं - मैंने उन्हें कुछ समय पहले किसी कार्यक्रम से लिया था और केवल थोड़ा बदल गया था। वीडियो मेमोरी क्षेत्र में मेमोरी आवंटित की जाती है। यदि संभव हो तो टेक्सचर को भी वहां रखा जाना चाहिए, गेटस्टैटिक विरामटेक्स्टचर के माध्यम से एक पॉइंटर का अनुरोध करना, अन्यथा प्रदर्शन तेजी से गिर जाएगा। बेशक, इस तरह के अनुरोधों के दौरान कोई गतिशील मेमोरी आवंटित नहीं की जाती है, लेकिन स्क्रीन और बनावट के लिए बस निर्दिष्ट पीएसपी पता स्थान का एक हिस्सा आवंटित किया जाता है। जहाँ तक मुझे याद है, PSP में केवल 2 मेगाबाइट वीडियो मेमोरी है - यह बहुत सारे टेक्सट को संग्रहीत करने के लिए बहुत छोटा है।

PSP GU प्रोग्रामिंग एक अंतर के साथ OpenGL के लिए प्रोग्रामिंग के समान है - कमांड के निष्पादन को प्रदर्शन सूची में उनके स्थान की आवश्यकता होती है, और इस सूची के लिए मेमोरी पूर्व-आवंटित और संरेखित होनी चाहिए:
स्थिर अहस्ताक्षरित चार __attribute __ (((16))) DisplayList [262144];
समन्वय परिवर्तन से संबंधित कमांडों को प्रदर्शन सूची की आवश्यकता नहीं होती है और इसे कार्यक्रम में कहीं भी निष्पादित किया जा सकता है।

आप उदाहरण के लिए, GU की शुरुआत कर सकते हैं:

 //    PSP #define VIRTUAL_SCREEN_SIZE 2048 //   #define SCREEN_ASPECT 16.0f/9.0f //   #define NEAR_PLANE_Z 5.0f //   #define FAR_PLANE_Z 4096.0f //  #define EYE_ANGLE 60.0f //  GU sceGuInit(); //        -    , .. GU_DIRECT sceGuStart(GU_DIRECT,DisplayList); //   -  ,    ,   (,   ) sceGuDrawBuffer(GU_PSM_8888,fbp0,SCREEN_LINE_WIDTH); //    -  ,   ,   sceGuDispBuffer(SCREEN_WIDTH,SCREEN_HEIGHT,fbp1,SCREEN_LINE_WIDTH); //   -           sceGuDepthBuffer(zbp,SCREEN_LINE_WIDTH); //      4096x4096 ( PSP    ) sceGuOffset(VIRTUAL_SCREEN_SIZE-(SCREEN_WIDTH/2),VIRTUAL_SCREEN_SIZE-(SCREEN_HEIGHT/2));//   //   -  -      sceGuViewport(VIRTUAL_SCREEN_SIZE,VIRTUAL_SCREEN_SIZE,SCREEN_WIDTH,SCREEN_HEIGHT); //      -      (     0  65535 !) sceGuDepthRange(65535,0); //        sceGuScissor(0,0,SCREEN_WIDTH,SCREEN_HEIGHT); sceGuEnable(GU_SCISSOR_TEST); sceGuEnable(GU_CLIP_PLANES); //   sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(EYE_ANGLE,SCREEN_ASPECT,NEAR_PLANE_Z,FAR_PLANE_Z); //      sceGuShadeModel(GU_SMOOTH); //   sceGuDepthFunc(GU_GEQUAL); sceGuEnable(GU_DEPTH_TEST); sceGuDepthMask(GU_FALSE); //   ,      sceGuFrontFace(GU_CCW); sceGuDisable(GU_CULL_FACE); //  sceGuDisable(GU_BLEND); sceGuBlendFunc(GU_ADD,GU_SRC_ALPHA,GU_ONE_MINUS_SRC_ALPHA,0,0); //   sceGuFinish(); sceGuSync(GU_SYNC_WAIT,GU_SYNC_FINISH); sceGuDisplay(GU_TRUE); 

GU के साथ काम खत्म करने के बाद, आपको sceGuTerm () को कॉल करना चाहिए।

किसी भी सुविधाजनक तरीके से आकार की बनावट (WidthImage; HeightImage) को लोड करने के बाद (बनावट डेटा के लिए एक डेटा सूचक - और वीडियो मेमोरी क्षेत्र में इसे प्राप्त करना बेहतर है), हम इसे प्रदर्शित कर सकते हैं।

  //  sceGuStart(GU_DIRECT,DisplayList); //     sceGuClearColor(0); sceGuClearDepth(0); sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT); //   sceGumMatrixMode(GU_PROJECTION); sceGumLoadIdentity(); sceGumPerspective(EYE_ANGLE,SCREEN_ASPECT,NEAR_PLANE_Z,FAR_PLANE_Z); sceGumUpdateMatrix();. //  sceGumMatrixMode(GU_TEXTURE); sceGumLoadIdentity(); sceGumMatrixMode(GU_VIEW); sceGumLoadIdentity(); sceGumMatrixMode(GU_MODEL); sceGumLoadIdentity(); //    sceGuColor(0xffffffff);//  sceGuEnable(GU_TEXTURE_2D); sceGuTexMode(GU_PSM_8888,0,0,0); sceGuTexImage(0,WidthImage,HeightImage,WidthImage,Data); sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA); sceGuTexFilter(GU_NEAREST,GU_NEAREST); sceGuTexWrap(GU_REPEAT,GU_REPEAT); sceGuTexScale(1,1); sceGuTexOffset(0,0); //      … sceGuDisable(GU_TEXTURE_2D); //    sceGuFinish(); sceGuSync(GU_SYNC_WAIT,GU_SYNC_FINISH); //  ,     sceDisplayWaitVblankStart(); sceGuSwapBuffers(); 

बहुभुज कैसे प्रदर्शित करें? जीयू ज्यामिति को आकर्षित करने के लिए, पीएसपी सभी बिंदुओं को एक सरणी में रखने के लिए कहता है, सूचक जिसे पहले sceGuGetMemory कमांड के साथ प्राप्त किया जाना चाहिए, इसे बाइट्स में अनुरोधित मेमोरी ब्लॉक के आकार को पास करना। इस पॉइंटर के आगे, आपको पॉइंट ऑफ़ एरे लिखना चाहिए और पीएसपी से उन्हें प्रदर्शित करने के लिए कहना चाहिए, उदाहरण के लिए, आवश्यक मापदंडों के साथ sceGumDrawArray कमांड। लेकिन इन डॉट्स का प्रारूप क्या है? पीएसपी के लिए, बिंदु डेटा को एक विशिष्ट क्रम में व्यवस्थित किया जाता है और एक बिंदु का वर्णन करने वाले सरणी का आकार 32 बाइट्स का एक से अधिक होना चाहिए: शीर्ष भार, बनावट निर्देशांक, बिंदु रंग, बिंदु से सामान्य, बिंदु समन्वय। उस क्रम में। प्रारूप से परेशान न होने के लिए, मैंने उनके साथ काम करने के लिए संरचनाओं और कार्यों के एक समूह को परिभाषित किया:

 //#pragma pack(1) //[for vertices(1-8)] [weights (0-8)] [texture uv] [color] [normal] [vertex] [/for] #pragma pack(1) //  struct SGuVertex { float X; float Y; float Z; }; //   struct SGuNormal { float Nx; float Ny; float Nz; }; //  struct SGuTexture { float U; float V; }; //  struct SGuColor { unsigned long Color; }; #pragma pack() #pragma pack(32) //  , , ,  struct SGuNVCTPoint { SGuTexture sGuTexture; SGuColor sGuColor; SGuNormal sGuNormal; SGuVertex sGuVertex; }; #pragma pack() void SetVertexCoord(SGuVertex &sGuVertex,float x,float y,float z);//   void SetNormalCoord(SGuNormal &sGuNormal,float nx,float ny,float nz);//   void SetTextureCoord(SGuTexture &sGuTexture,float u,float v);//   void SetColorValue(SGuColor &sGuColor,unsigned long color);//  //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::SetVertexCoord(SGuVertex &sGuVertex,float x,float y,float z) { sGuVertex.X=x; sGuVertex.Y=y; sGuVertex.Z=z; } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::SetNormalCoord(SGuNormal &sGuNormal,float nx,float ny,float nz) { sGuNormal.Nx=nx; sGuNormal.Ny=ny; sGuNormal.Nz=nz; } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::SetTextureCoord(SGuTexture &sGuTexture,float u,float v) { sGuTexture.U=u; sGuTexture.V=v; } //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- void CMain::SetColorValue(SGuColor &sGuColor,unsigned long color) { sGuColor.Color=color; } 

फिर आप ज्यामिति को निर्दिष्ट कर सकते हैं (इस मामले में, वर्ग), उदाहरण के लिए, इस तरह:

  //  SGuNVCTPoint sGuNVCTPoint; vector<SGuNVCTPoint> vector_point; SetVertexCoord(sGuNVCTPoint.sGuVertex,-100,100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,0,0); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); SetVertexCoord(sGuNVCTPoint.sGuVertex,100,100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,1,0); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); SetVertexCoord(sGuNVCTPoint.sGuVertex,100,-100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,1,1); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); SetVertexCoord(sGuNVCTPoint.sGuVertex,-100,-100,0); SetTextureCoord(sGuNVCTPoint.sGuTexture,0,1); SetNormalCoord(sGuNVCTPoint.sGuNormal,0,0,1); SetColorValue(sGuNVCTPoint.sGuColor,0xFFFFFFFF); vector_point.push_back(sGuNVCTPoint); 

और इसे आउटपुट करें, उदाहरण के लिए, इस तरह:

  size_t vertex_amount=vector_point.size(); SGuNVCTPoint *sGuNVCTPoint_Ptr=(SGuNVCTPoint*)sceGuGetMemory(vertex_amount*sizeof(SGuNVCTPoint)); if (sGuNVCTPoint_Ptr!=NULL) { for(size_t n=0;n<vertex_amount;n++) sGuNVCTPoint_Ptr[n]=vector_point[n]; sceGumDrawArray(GU_TRIANGLE_FAN,GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D|GU_NORMAL_32BITF|GU_TEXTURE_32BITF,vertex_amount,0,sGuNVCTPoint_Ptr); } 

आउटपुट के लिए, मैंने sceGumDrawArray फ़ंक्शन को इंगित किया कि मैं वास्तव में क्या आकर्षित करता हूं और बिंदु का प्रारूप क्या है (GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSF3_3D | GU_NORMAL_32BITF | GU_TEXTURE_32BITF - बिंदु रंग का बिंदु है) ड्राइंग केवल त्रिकोणों के साथ संभव है। लेकिन यह सब नहीं है ...

काम करने के लिए सब कुछ लगता है, लेकिन यह केवल तभी काम करता है जब सभी बिंदु आंखों के सामने हों और दिखाई दें। एक बार कम से कम एक बिंदु कुछ धूमिल दूरी में चला जाता है, जीयू पूरे बहुभुज को खींचने से इनकार करता है। जैसा कि मैं इसे समझता हूं, PSP के GU को चार क्लिपिंग विमानों (बाएं, दाएं, ऊपर और नीचे (और सामने वाला अपने आप बाहर हो जाएगा) के सापेक्ष) की आवश्यकता होती है, बिंदु इस वॉल्यूम के अंदर स्थित है, अन्यथा GU इसे प्रदर्शित करने के लिए सहमत नहीं है। समस्या। लेकिन खेलों में, 3 डी ग्राफिक्स मौजूद हैं और ऐसी कलाकृतियों का अवलोकन नहीं किया जाता है! आइए देखें कि वे इस समस्या को PSP क्वेक 1 में कैसे हल करते हैं, क्योंकि विश्लेषण के लिए स्रोत उपलब्ध हैं।

हम स्रोत विश्लेषण से क्या देखते हैं? लेकिन वास्तव में, यह वही है:

  //   sceGumMatrixMode(GU_PROJECTION); ScePspFMatrix4 projection_matrix; sceGumStoreMatrix(&projection_matrix); //    sceGumMatrixMode(GU_VIEW); ScePspFMatrix4 view_matrix; sceGumStoreMatrix(&view_matrix); //   sceGumMatrixMode(GU_MODEL); ScePspFMatrix4 model_matrix; sceGumStoreMatrix(&model_matrix); sceGuFinish(); //   view-projection ScePspFMatrix4 projection_view_matrix; MultiplyScePspFMatrix4(view_matrix,projection_matrix,projection_view_matrix); //   view-projection-model ScePspFMatrix4 projection_view_model_matrix; MultiplyScePspFMatrix4(model_matrix,projection_view_matrix,projection_view_model_matrix); //  view-model ScePspFMatrix4 view_model_matrix; MultiplyScePspFMatrix4(model_matrix,view_matrix,view_model_matrix); //      (, , , ) ScePspFVector4 frustum[4];//   : ax+by+cz+d=0 // frustum[0].x=projection_view_model_matrix.x.w+projection_view_model_matrix.xx; frustum[0].y=projection_view_model_matrix.y.w+projection_view_model_matrix.yx; frustum[0].z=projection_view_model_matrix.z.w+projection_view_model_matrix.zx; frustum[0].w=projection_view_model_matrix.w.w+projection_view_model_matrix.wx; NormaliseScePspFVector4(frustum[0]); // frustum[1].x=projection_view_model_matrix.xw-projection_view_model_matrix.xx; frustum[1].y=projection_view_model_matrix.yw-projection_view_model_matrix.yx; frustum[1].z=projection_view_model_matrix.zw-projection_view_model_matrix.zx; frustum[1].w=projection_view_model_matrix.ww-projection_view_model_matrix.wx; NormaliseScePspFVector4(frustum[1]); // frustum[2].x=projection_view_model_matrix.xw-projection_view_model_matrix.xy; frustum[2].y=projection_view_model_matrix.yw-projection_view_model_matrix.yy; frustum[2].z=projection_view_model_matrix.zw-projection_view_model_matrix.zy; frustum[2].w=projection_view_model_matrix.ww-projection_view_model_matrix.wy; NormaliseScePspFVector4(frustum[2]); // frustum[3].x=projection_view_model_matrix.x.w+projection_view_model_matrix.xy; frustum[3].y=projection_view_model_matrix.y.w+projection_view_model_matrix.yy; frustum[3].z=projection_view_model_matrix.z.w+projection_view_model_matrix.zy; frustum[3].w=projection_view_model_matrix.w.w+projection_view_model_matrix.wy; NormaliseScePspFVector4(frustum[3]); 

यही है, निष्कर्ष 1 से पहले, वे निष्कर्ष से पहले सभी बिंदुओं को उस खंड के अंदर स्थानांतरित करते हैं जो दृश्य को प्रतिबंधित करता है, या उन्हें पूरी तरह से बाहर फेंक देता है (यदि संपूर्ण आंकड़ा दिखाई नहीं देता है)। यह कैसे करें? आपको बस तीन मैट्रिसेस - GU_PROJECTION, GU_MODEL, GU_VIEW पढ़ना होगा। उन्हें गुणा करें और अंतिम समन्वय परिवर्तन मैट्रिक्स प्राप्त करें। इस मैट्रिक्स से, आप दृश्य को प्रतिबंधित करने वाले सभी आवश्यक विमानों को बाहर निकाल सकते हैं (परिणामस्वरूप वेक्टर के 4 घटक एक विमान को समीकरण अक्ष + + cz + w = ​​0 से परिभाषित करते हैं)। (a, b, c) सामान्य वेक्टर है, और w = a * x0 + b * y0 + c * z0 - समतल का एक निश्चित बिंदु (x0, y0, z0) है। हमें खुद बिंदु के निर्देशांक की आवश्यकता नहीं है - बस w पता है।

कतरन निम्नानुसार की जाती है (एक चक्र में बदले में उपर्युक्त चार विमानों के लिए):

  //  vector<SGuNVCTPoint> vector_clip_point; for(long n=0;n<4;n++) { float nx=frustum[n].x; float ny=frustum[n].y; float nz=frustum[n].z; float w=frustum[n].w; Clip(vector_point,vector_clip_point,nx,ny,nz,w); vector_point=vector_clip_point; } 

लेकिन इस फोकस के लिए, हमें निम्नलिखित कार्यों की आवश्यकता है (क्वेक 1 से विघटित):

 //---------------------------------------------------------------------------------------------------- //      //---------------------------------------------------------------------------------------------------- void CMain::GetIntersectionPlaneAndLine(const SGuNVCTPoint& A,const SGuNVCTPoint& B,SGuNVCTPoint& new_point,float nx,float ny,float nz,float w) { new_point=A; float ax=A.sGuVertex.X; float ay=A.sGuVertex.Y; float az=A.sGuVertex.Z; float au=A.sGuTexture.U; float av=A.sGuTexture.V; float bx=B.sGuVertex.X; float by=B.sGuVertex.Y; float bz=B.sGuVertex.Z; float bu=B.sGuTexture.U; float bv=B.sGuTexture.V; float dx=bx-ax; float dy=by-ay; float dz=bz-az; float du=bu-au; float dv=bv-av; float top=(nx*ax)+(ny*ay)+(nz*az)+w; float bottom=(nx*dx)+(ny*dy)+(nz*dz); float time=-top/bottom; float vx=ax+time*dx; float vy=ay+time*dy; float vz=az+time*dz; float vu=au+time*du; float vv=av+time*dv; //   SetVertexCoord(new_point.sGuVertex,vx,vy,vz); SetTextureCoord(new_point.sGuTexture,vu,vv); } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void CMain::Clip(const vector<SGuNVCTPoint>& vector_point_input,vector<SGuNVCTPoint>& vector_point_output,float nx,float ny,float nz,float w) { vector_point_output.clear(); long point=vector_point_input.size(); for(long n=0;n<point;n++) { long next_p=n+1; if (next_p>=point) next_p-=point; const SGuNVCTPoint *sGuNVCTPoint_Current_Ptr=&(vector_point_input[n]); float current_vx=sGuNVCTPoint_Current_Ptr->sGuVertex.X; float current_vy=sGuNVCTPoint_Current_Ptr->sGuVertex.Y; float current_vz=sGuNVCTPoint_Current_Ptr->sGuVertex.Z; //     float current_ret=current_vx*nx+current_vy*ny+current_vz*nz+w; const SGuNVCTPoint *sGuNVCTPoint_Next_Ptr=&(vector_point_input[next_p]); float next_vx=sGuNVCTPoint_Next_Ptr->sGuVertex.X; float next_vy=sGuNVCTPoint_Next_Ptr->sGuVertex.Y; float next_vz=sGuNVCTPoint_Next_Ptr->sGuVertex.Z; //     float next_ret=next_vx*nx+next_vy*ny+next_vz*nz+w; if (current_ret>0)//   { if (next_ret>0)//   { vector_point_output.push_back(*sGuNVCTPoint_Next_Ptr); } else { //    SGuNVCTPoint sGuNVCTPoint_New; GetIntersectionPlaneAndLine(*sGuNVCTPoint_Current_Ptr,*sGuNVCTPoint_Next_Ptr,sGuNVCTPoint_New,nx,ny,nz,w); vector_point_output.push_back(sGuNVCTPoint_New); } } else//    { if (next_ret>0)//   { //    SGuNVCTPoint sGuNVCTPoint_New; GetIntersectionPlaneAndLine(*sGuNVCTPoint_Current_Ptr,*sGuNVCTPoint_Next_Ptr,sGuNVCTPoint_New,nx,ny,nz,w); vector_point_output.push_back(sGuNVCTPoint_New); //   vector_point_output.push_back(*sGuNVCTPoint_Next_Ptr); } } } } 

और केवल इस तरह के कट-ऑफ का प्रदर्शन करने के बाद, आप अंत में GU का उपयोग करते हुए PSP पर तीन-आयामी ग्राफिक्स का आउटपुट प्राप्त करते हैं। आप एक खेल बना सकते हैं! :)



वैसे, आप वैक्टर के स्केलर उत्पाद के लिए PSP वेक्टर प्रोसेसर का भी उपयोग कर सकते हैं। उदाहरण के लिए, यहां एक फ़ंक्शन है जो यह निर्धारित करता है कि क्या कतरन की आवश्यकता है (पीएसपी के लिए एक ही क्वेक 1 से टुकड़ों को फाड़ दिया जाता है):

 //  vector<SGuNVCTPoint> vector_clip_point; //   PSP __asm__ volatile ( "ulv.q C700, %0\n" //    "ulv.q C710, %1\n" //    "ulv.q C720, %2\n" //    "ulv.q C730, %3\n" //    :: "m"(FrustumPlane[0]),"m"(FrustumPlane[1]),"m"(FrustumPlane[2]),"m"(FrustumPlane[3]) ); //   long vertex=vector_point.size(); bool clipping=false; for(long n=0;n<vertex;n++) { ScePspFVector4 current_vertex; current_vertex.x=vector_point[n].sGuVertex.X; current_vertex.y=vector_point[n].sGuVertex.Y; current_vertex.z=vector_point[n].sGuVertex.Z; current_vertex.w=1; float ret1,ret2,ret3,ret4; __asm__ volatile ( "ulv.q C610, %4\n" //      "vone.s S613\n" //       "vdot.q S620, C700, C610\n" // s620 =    "vdot.q S621, C710, C610\n" // s621 =    "vdot.q S622, C720, C610\n" // s622 =    "vdot.q S623, C730, C610\n" // s623 =    "mfv %0, S620\n" // out1 = s620 "mfv %1, S621\n" // out2 = s621 "mfv %2, S622\n" // out3 = s622 "mfv %3, S623\n" // out4 = s623 : "=r"(ret1), "=r"(ret2), "=r"(ret3), "=r"(ret4) : "m"(current_vertex) ); if (ret1<0 || ret2<0 || ret3<0 || ret4<0)//  { clipping=true; break; } } 

यहां सब कुछ सरल है - उन्होंने विमान के वैक्टर और रजिस्टर में निर्देशांक को रखा और VFPU को स्केलर उत्पाद करने के लिए कहा।

→ सबसे सरल बनावट प्रदर्शन आवेदन के लिए लिंक

→ GU का उपयोग करते हुए PSP इंजन से लिंक करें

PS मुझे पता है कि PSP के लिए प्रोग्रामिंग पेशेवर हैं। शायद वे आपको बताएंगे कि पीएसपी जीयू की व्यवस्था क्यों की गई है और इसके साथ सही तरीके से कैसे काम किया जाए।

Source: https://habr.com/ru/post/hi406049/


All Articles