الشبكة العربية لمطوري الألعاب

مبتدئ  maya مشاركة 1

السلام عليكم

لدي ملف من نوع خاص و اريد قراءته

الملف مبدئيا هكذا


v 0.0 0.0 0.0
 v 0.0 0.0 1.0
 v 0.0 1.0 0.0
 v 0.0 1.0 1.0
 v 1.0 0.0 0.0
 v 1.0 0.0 1.0
 v 1.0 1.0 0.0 
v 1.0 1.0 1.0
 vn 0.0 0.0 1.0 
vn 0.0 0.0 -1.0 
vn 0.0 1.0 0.0 
vn 0.0 -1.0 0.0 
vn 1.0 0.0 0.0 
vn -1.0 0.0 0.0
 f 1//2 7//2 5//2 
f 1//2 3//2 7//2
 f 1//6 4//6 3//6 
 f 1//6 2//6 4//6 
 f 3//3 8//3 7//3  
f 3//3 4//3 8//3  
f 5//5 7//5 8//5 
 f 5//5 8//5 6//5  
f 1//4 5//4 6//4  
f 1//4 6//4 2//4 
 f 2//1 6//1 8//1  
f 2//1 8//1 4//1

هذا الملف من النوع .OBJ الذي نستخدمه فيما بعد للرسم ب OPENGL
هذا موقع يشرع كيففية تواجد الملفات .obj
http://www.royriggs.com/obj.html
بحيث


v وهى vertexs للمجسم

vn وهى normal vertexs

البيانات التى تبدأ بحرف f هى سطوح المجسم والتى تكون على هيئة مثلثات فى الغالب

طيب والعلامه // تشير الى ان ما على يسارها vertex وما على يمينها normal vertex

مهمة normal

يعتبر المتجه العمودى هو الاساس لتحديد الظاهر و الخفى. كذلك للقيام بالاسقاط الهندسى بشكل مناسب و اخيراً التعامل مع الأضاءة.

انا اريد ان اقراه لانني اريد ان استعمله فيما بعد لرسم المجسم
هاهو الكود المبدئي لكنه في الحقيقة ما زال لم يكمل بعد لم اضف له بعد VN و
traingle اضفتها لانني ان اردت ان ارسم مجسم اقسمه على شكل مثلثات


#include 

#include 

#include 



struct Triangle {



       int v1;

       int v2;

       int v3;



};



struct Vertex {



      float x;

      float y;

      float z;



};



using namespace std;



static void display(void)

{    

    // move the view a lil down so we could get the tree.obj in the centre of screen

    glTranslatef(0.0, -0.50, 0.0);



    // clear all pixels

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0, 1.0, 1.0);



    Vertex v[50000];

    Triangle t[50000];



    int vertexCount = 0;

    int triangleCount = 0;



    char line[100];



    FILE *fp = fopen("cube.obj","r");



    if (fp != NULL)

    {

        while (fgets(line, 99, fp))

        {

              if (line[0] == 'v')

              {

                  sscanf(line, "%*c %f %f %f", &v[vertexCount].x, &v[vertexCount].y, &v[vertexCount].z);                  

                  vertexCount++;

              } 

              else if (line[0] == 'f')

              {

                  sscanf(line, "%*c %d %d %d", &t[triangleCount].v1, &t[triangleCount].v2, &t[triangleCount].v3);

                  triangleCount++;

              }   

        }   

    }



    fclose(fp);

 
لكن العمل بالجداول غير منطقي لان الملف لا نعرف كم فيه من vertex لذا قررت التبديل و العمل ب vector

اي


vector v;
vector t;

لكنني لم اعرف كيف ابدل


v[vertexCount].x





اي كيف اضيف في الجدول الديناميكي

ارجو ان تكونوا قد فهمتم طريقتي و فهمتم ماذا يوجد في الملف و التعقيد الذي فيه لانني لا اعرف كم v توجد
ن اسالكم ايضا هل  الطريقة هذه التي اعمل بها هي طريقة index face set  لانني سمعت انها تستعمل لقراءة الملفات من هذا النوع
بحيث  اولا نقرا الملف بالكامل و نحسب كم توجد من v و كم توجد من f و كم من vn  و كم من vt
ثم نعرف لكل نوع table او جدول لكني لم اعرف كيفية لاعمل الدقيق بهذه الطريقة

خبير  Mohammad Khashashneh مشاركة 2

أعتقد بأن هذا سيفي بالغرض.

#include 
#include 
#include 
#include  // added code

struct Triangle {
       int v1;
       int v2;
       int v3;
};

struct Vertex {
      float x;
      float y;
      float z;
};

using namespace std;
static void display(void)
{    
    // move the view a lil down so we could get the tree.obj in the centre of screen
    glTranslatef(0.0, -0.50, 0.0);
    // clear all pixels
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    //Vertex v[50000];        // deleted code
    //Triangle t[50000];     // deleted code
    //int vertexCount = 0;    // deleted code
    //int triangleCount = 0;    // deleted code
    vector v;    // added code
    vector t; // added code
    char line[100];
    FILE *fp = fopen("cube.obj","r");
    if (fp != NULL)
    {
    Vertex tempV;
    Triangle tempT;
        while (fgets(line, 99, fp))
        {
              if (line[0] == 'v')
              {
                  sscanf(line, "%*c %f %f %f", &tempV.x, &tempV.y, &tempV.z);    // modified code
                  //vertexCount++;    // deleted code
          v.push_back(tempV);    // added code
              } 
              else if (line[0] == 'f')
              {
                  sscanf(line, "%*c %d %d %d", &tempT.v1, &tempT.v2, &tempT.v3); // modified code
                  //triangleCount++;    // deleted code
          t.push_back(tempT);    // added code
              }   
        }
       
    }

    fclose(fp);
....


لكن يجب أن تفرأ أكثر عن vector.  لأني سمعت أن إضافة عنصر واحد كل مرة بطيئ  و بعض الimplementations تحجز ضعف الcapacity الحالية بعد كل push_back فوق ال capacity و ذلك مضيعة للذاكرة. فالأفضل استخدام الreserve method. مثلا استهلال ال vectorب 100 عنصر بداية، ثم إضافة 100 أخرى بعد نفاذها. 

محمد خشاشنة

من سار على الدرب وصل, من جد وجد...
بس عتبك على اللي بيسمع

مبتدئ  maya مشاركة 3

السلام عليكم
اولا اريد ان اشكرك  على المساعدة فهي حقا جيدة لكن هناك مشكلة صغيرة ظهرت لي اثناء تصفحي لبعض ملفات  من هذا النوع  .obj لاجسام مختلفة تفاجات لانني وجدت انه
هناك بعض الملفات اجدها مكتوبة هكذا


g  objet
usemlt chrome //  اسم الصورة المستعملة للاكساء اي اننا سنضيف جدول به اسم الصورة الخاصة بالاكساء مع النقاط المخصصة لها 
 v  -0.0729698  0.416975  -0.0005 
v -0.07242360.417279  0.00589344
v  -0.0722358  0.422193  -0.00559925


vt  0.12 0.01 0.03
vt .......// اي مثل سابقتها 
vt .......
vn .......
vn .......... 
f 
f
g head
usemelt  head1
v.............
v.........
vt ..........
vn......              
 فكما تلاحظ ان ملف واحد من الممكن ان نجد فيه اكثر من تصميم لمجسم او بالاحرى نقسم المجسم لاجزاء كل جزء يبدا ب g  اي كما اظن اننا يجب ان نضيف جدول اخر نضع فيه g  و نرطبطهم بvertex الخاصة بهم هذا من جهة
من جهة اخرى

f هذه كتابتها
f v1[/vt1][/vn1] v2[/vt2][/vn2] v3[/vt3][/vn3]...
فمن ملف لاخر او من g لاخرى في نفس الملف يختلف تمثيلها فقد تكون بها 3 نقاط و قد  عالجت هذه الحالة ب triangle  لكن ان كانت اربع لم اعالجه او خمس نقاط اي على سكل خماسي  لم اعرف كيف يمكنني ان اعرف من البداية هذا

خبير مدير وسام البهنسي مشاركة 4

صيغة ملفات OBJ قادرة على حفظ معلومات أكثر من مجسم إضافة إلى العلاقات الشجرية بينها. لذلك إن كنت تريد دعم كامل مواصفات ملفات OBJ فإنك ستحتاج إلى بنية برمجية قادرة على استيعابها.
 
الكود الذي قمتَ بكتابته قادر على استقبال معلومات مجسم واحد فقط مكون من مجموعة مثلثات. الآن إن أردتَ دعم عدة مجسمات فإني أقترح إعادة هيكلة طريقة حفظ البيانات لتصبح متمركزة حول تعريف المجسم. يعني:
 
بنية مجسم - أعضاؤها :
  * اسم المجسم
  * قائمة إحداثيات نقاطه الفراغية
  * قائمة النواظم
  * قائمة المثلثات (أو المضلعات إن أحببت)
  * اسم المادة المستخدمة
 
الآن عندما تقرأ الملف، وفي كل مرة تواجه التعليمة g فإنك تفتتح مجسماً جديداً وتبدأ بتعبئة معلوماته كما ترد في الملف.
كمثال:


struct Geometry
{
  string name;
  vector vertices;
  vector normals;
  vector triangles;
  string materialName;
};
 
vector<geometry*> allGeometry;
 
 
int main()
{
  Geometry *geom = NULL;
  .

  .
  .
  // قراءة الملف
  .
  .
    if (line[0] == 'g')
    {
       // مجسم جديد. إن كنا قد قرأنا مجسماً سابقاً فأضفه لقائمة المجسمات في الملف
       if (geom != NULL)
         allGeometry.push_back(geom);
 
       geom = new Geometry(); // افتتح مجسماً جديداً
    }
    else if (line[0] == 'v')
    {
       Vertex vtx;
       sscanf(line, "%*c %f %f %f", &vtx.x, &vtx.y, &vtx.z);
       geom->vertices.push_back(vtx); // إضافة رأس للمجسم
    }
  .
  .
  .
}
 
أنصحك بعدم تشويش نفسك بتفاصيل الأداء الآن. فقط اجعل الكود قادراً على العمل بشكل صحيح.

وسام البهنسي
مبرمج في إنفيديا وإنفريمز

خبير مدير وسام البهنسي مشاركة 5

وشكراً أختي maya على الكود، فقد تعلمتُ منه شيئاً جديداً:


sscanf(line, "%*c %f %f %f", &vtx.x, &vtx.y, &vtx.z);
 
لم أكن أعلم أنك تستطيع استخدام النجمة * لإخبار scanf بتجاهل هذا المُدخل.  ☺

وسام البهنسي
مبرمج في إنفيديا وإنفريمز

مبتدئ  maya مشاركة 6

وفي 09/ذو الحجة/1430 02:23 ص، قال وسام البهنسي متحمساً:

لم أكن أعلم أنك تستطيع استخدام النجمة * لإخبار scanf بتجاهل هذا المُدخل. 

السلام عليكم
و لو انا استفدت منكم اكثر و مازلنا نستفيد  فالمعلومات التي اضفتها بعد ان انضممت هنا لا تقدر فنا مبتداة جدا في سي++  و ليس لدي افكار برمجية كبيرة



وفي 09/ذو الحجة/1430 02:20 ص، ظهر شبح ابتسامة على وجه وسام البهنسي وهو يقول:

أنصحك بعدم تشويش نفسك بتفاصيل الأداء الآن. فقط اجعل الكود قادراً على العمل بشكل صحيح.

لم افهم ماذا تعني بتفاصيل الاداء لانني حتى يعمل الكود بشكل صحيح في الاخير يجب ان نرسم المجسم

أما في 09/ذو الحجة/1430 02:20 ص، فقد تنهد وسام البهنسي بارتياح وهو يرد:

struct Geometry
{ string name; vector vertices; vector normals; vector triangles; string materialName;}; 

ما رايك ان نضيف رقم لهذا المجسم  حتى عندما نريد الرسم تكون الامور سهلة بالتعمل بالارقام و ليس بالاسماء
النقطة الاخرى و هي مشكلة face لقد فكرت في هذه البنية ما رايك فيها اولا
جول اسمه face به
1- struct من نوع vertex لاننا لا نعلم كم من نقطة به و يختلف من واحد لاخر
2-struct من نوع normal  و struct من نوع textur
و انا اكتب في هذه الاسطر جاءتني فكرة ما رايك اننا بدل ان نضع كل  هذه struct  يكفي انه مثلا اذا قرانا اسم اول vertex لا اكتبه انما اربطه فقط بالجدول الذي به vertex  و هكذا بالنسبة للبقية لكني لم اعرف كيف اطبق هذا
هل لك فكرة اخرى و هل استطيع ان اطبق * حتلى لا يقرا /

مبتدئ  maya مشاركة 7

السلام عليكم
بعد كتابتي للرد قبل قليل وجدت فكرة اخرى ما رايك بها

لتركيبة التالية هي عبارة عن entry في ال face حيث كما قلت يمكن ان يكون هناك الكثير.

وكل entry يتكون من v,vt,vn
ملاحظة (في الحقيقة لم افهم  جيدا هذا المفهوم الذي وجدته يستعمل في حالات مماثلة  فحاولت تطبيقه على حالتي و لا ادري هل كلمة entry هذه يعفرها سي ++ ام كتبها صاحب الموضوع  و انا استعملتها مثله🙁 لا ادري لانني وجدتها  معرفة في سي++ لكني لم افهمها فهمت ما يمثله الكود قط و حاولت ان اعمل مثله)
struct Face_Entry {
    Vertex v;
    Vertex_Texture vt;
    Vertex_Normal vn;
    
    bool vt_avialable;// هل يوجد اكساء ام لا 
    bool vn_avialable;// هل يوجد ناظم ام لا 
};


تعريف ال face


struct Face {
    vector e;
    
};






لان ننشئ مصفوفة لكي نقرأ اليهم من الملف.

vector faces;
ما رايك  في هذا 
انا اقدر رايك و اضافاتك