Accueil

CPC


 Dev C sur CPC :

  • le C sur CPC
  • SDCC débuter
  • fichier BAT pour compiler
  • Dessiner Sur CPC
  • Optimiser le dessin
  • Ecrire du texte
  • Lire un fichier
  • Ecrire un fichier
  • Swap d'écran
  • CLS ultra rapide
  • H line
  • Attaquer le CRTC
  • Full Overscan
  • Put pixel très rapide
  • Afficher une image
  • Slide show 1
  • Bézier
  • faire un fichier pour Bézier

  • Quelque fonctions utile

  • Animation
  • 3D
  • Raster
  • Manche a balais

    Le plan du Site

  •  
      Ici les nouvelle du site  
     
    Recherche ?
    Saissisez un mot clé

     
      Quelques chiffres
    Visiteurs:11039
    Visiteurs aujourd'hui:17
     
     
    Me contacter
    Donnez votre avis
     
    Le site de Steph : Le CPC

    3D temps IREEL

    Tracé points


    On vas se faire ici un programme pour afficher un cube en point, on vas faire comme le programme basic que je vous est présenté juste avant.
    J'ai ajouté une fonction GetTime_s qui permet de récupérer le timer du CPC, celui ci augmente de 1 tout les 1/300 de seconde, donc pour avoir le temps en seconde, on divise le nombre affiché par 300.
    Voici le programme :

    ////////////////////////////////////////////////////////////////////////
    // cube1.c
    // Affichage d'un cube 3d en point
    // VERSION 
    ////////////////////////////////////////////////////////////////////////
    #include "conio2.h"
    #include 
    #include 
    
    #define KM_WAIT_CHAR_s \
    	__asm \
    	call #0xBB06 \
    	__endasm
    
    #define  SCR_SET_MODE1_s \
    	__asm	ld a,#1 \
    	call #0xBC0E \
    	__endasm;
    
    typedef struct
    {
      long x,y,z;
    } point3D;
    
    typedef struct
    {
      int x,y;
    } point2D;
    
    
    point3D Sommet[8];   // les sommets du cube
    point3D Point3D[8];  // les sommets apres rotation
    point2D Point2D[8];  // les sommets apres projection
    
    int Nb_points;
    
    int Xoff;
    int Yoff;
    int Zoff;
    
    float Sin[360],Cos[360];   /* Tableaux precalcules de sinus et cosinus */
    float matrice[3][3];       /* Matrice de rotation 3*3 */
    
    int xa,ya,za;
    
    void PutPixelMode1(int nX, unsigned char nY, unsigned char nColor)
    {
      int nPixel = nX % 4;
      unsigned char *pAddress = (unsigned char *)((unsigned int)(0xC000 + ((nY / 8) * 80) + ((nY % 8) * 2048) + (nX / 4)));
       
      if(nPixel == 0)
      {
        *pAddress &= 119;
    
        if(nColor & 1)
          *pAddress |= 128;
        if(nColor & 2)
          *pAddress |= 8;
      }
      else if(nPixel == 1)
      {
        *pAddress &= 187;
    
        if(nColor & 1)
          *pAddress |= 64;
        if(nColor & 2)
          *pAddress |= 4;
      }
      else if(nPixel == 2)
      {
        *pAddress &= 221;
    
        if(nColor & 1)
          *pAddress |= 32;
        if(nColor & 2)
          *pAddress |= 2;
      }
      else //nPixel == 3
      {
        *pAddress &= 238;
    
        if(nColor & 1)
          *pAddress |= 16;
        if(nColor & 2)
          *pAddress |= 1;
      }
    }
    
    void Init_Sinus(void)
    {
    	int i;
    	// pAddress, c'est juste pour faire clignoter un point sur l'ecran, istoire de voire qu'il se passe quelque chose !
    	unsigned char *pAddress = (unsigned char *)((unsigned int)0xC004);
    	*pAddress = 0xff;
    		
    	for(i=0;i<360;i++)
    	{
    		Sin[i]=sinf( (i * 3.1415927 / 180) );
    		Cos[i]=cosf( (i * 3.1415927 / 180) );
    
    		*pAddress = !*pAddress;
    	}
    }
    
    
    void Rotation(int Xa, int Ya, int Za)
    {
      int i;
    
      // Calcul de la matrice de rotation 3*3
      matrice[0][0] = Cos[Za]*Cos[Ya];
      matrice[1][0] = Sin[Za]*Cos[Ya];
      matrice[2][0] = -Sin[Ya];
    
      matrice[0][1] = Cos[Za]*Sin[Ya]*Sin[Xa] - Sin[Za]*Cos[Xa];
      matrice[1][1] = Sin[Za]*Sin[Ya]*Sin[Xa] + Cos[Xa]*Cos[Za];
      matrice[2][1] = Sin[Xa]*Cos[Ya];
    
      matrice[0][2] = Cos[Za]*Sin[Ya]*Cos[Xa] + Sin[Za]*Sin[Xa];
      matrice[1][2] = Sin[Za]*Sin[Ya]*Cos[Xa] - Cos[Za]*Sin[Xa];
      matrice[2][2] = Cos[Xa]*Cos[Ya];
    
    
      // Rotation des sommets de l'objet
      for(i=0;i < Nb_points;i++)
      {
        Point3D[i].x =   matrice[0][0]*Sommet[i].x
    				   + matrice[1][0]*Sommet[i].y
    				   + matrice[2][0]*Sommet[i].z;
    
        Point3D[i].y =   matrice[0][1]*Sommet[i].x
    				   + matrice[1][1]*Sommet[i].y
    				   + matrice[2][1]*Sommet[i].z;
    
        Point3D[i].z =   matrice[0][2]*Sommet[i].x
    				   + matrice[1][2]*Sommet[i].y
    				   + matrice[2][2]*Sommet[i].z;
      }
    }
    
    void Projection(void)
    {
      int i;
    
      for(i=0;i < Nb_points;i++)
      {
        Point2D[i].x=(Point3D[i].x<<8)/(Point3D[i].z+Zoff)+Xoff;
        Point2D[i].y=(Point3D[i].y<<8)/(Point3D[i].z+Zoff)+Yoff;
      }
    }
    
    void Initialiser(void)
    {
      Sommet[0].x = -100;  Sommet[0].y = -100;  Sommet[0].z = -100;
      Sommet[1].x =  100;  Sommet[1].y = -100;  Sommet[1].z = -100;
      Sommet[2].x =  100;  Sommet[2].y =  100;  Sommet[2].z = -100;
      Sommet[3].x = -100;  Sommet[3].y =  100;  Sommet[3].z = -100;
      Sommet[4].x =  100;  Sommet[4].y = -100;  Sommet[4].z =  100;
      Sommet[5].x = -100;  Sommet[5].y = -100;  Sommet[5].z =  100;
      Sommet[6].x = -100;  Sommet[6].y =  100;  Sommet[6].z =  100;
      Sommet[7].x =  100;  Sommet[7].y =  100;  Sommet[7].z =  100;
    }
    
    void DesPoint(unsigned char couleur)
    {
    unsigned char i;
    
      for (i=0;i < Nb_points;i++)
      {
    	PutPixelMode1(Point2D[i].x, Point2D[i].y, couleur);
      }
    }
    
    void Afficher(unsigned char couleur)
    {
    	// ON EFFACE TOUT 
    	__asm
    		call #0xBBDB
    	__endasm;
    	
    	// On dessine 
    	// Que les point
    	DesPoint(couleur);
    }
    
    unsigned char char3,char4;
    // donne le temps écoule en 1/300' de seconde depuis l'allumage du CPC
    // ou BD10: positionne le compteur interne à une valeur précise
    unsigned int GetTime_s()
    {
    	unsigned int nTime = 0;
    
    	__asm
    	CALL #0xBD0D ;KL TIME PLEASE
    	PUSH HL
    	POP DE
    	LD HL, #_char3
    	LD (HL), D
    	LD HL, #_char4
    	LD (HL), E
    	__endasm;
    
    	nTime = (char3 << 8) + char4;
    
    	return nTime;
    }
    
    
    void main()
    {
    	unsigned int nTimeStart = 0;
    	unsigned int nTime1 = 0;
    	unsigned int nTime2 = 0;
    
    	Nb_points = 8;
    
    	Xoff = 160;
    	Yoff = 100;
    	Zoff = 600; 
      
    	//SCR_SET_MODE 1
    	__asm
    		ld a,#1
    		call #0xBC0E
    	__endasm;
    
    
    	nTimeStart = GetTime_s();
    	// calcule des table Sin et Cos...
    	Init_Sinus();
    	nTime1 = GetTime_s() - nTimeStart;  
    	gotoxy(1,1);printf("Time calculate Sin/Cos : %d", nTime1);
    	KM_WAIT_CHAR_s;
    
    	// initialise les valeurs de lobjet 3D (le cube)
    	Initialiser();
    	xa=ya=za=0;
    
    
    	// Animation de note cube jusqu'a pression d'une touche
    	while( 1 )
    	{
    		nTimeStart = GetTime_s();
    		Rotation(xa,ya,za);
    		Projection();
    		nTime1 = GetTime_s() - nTimeStart;
    
    		nTimeStart = GetTime_s();
    		Afficher(1);
    		nTime2 = GetTime_s() - nTimeStart;
    
    		xa=(xa+2)%360;
    		ya=(ya+6)%360;
    		za=(za+2)%360;
    
    		gotoxy(1,1);printf("Time calculate 3D : %d", nTime1);
    		gotoxy(1,2);printf("Time draw 3D : %d", nTime2);
    
    		if(kbhit())
    			break;
    	}
    
    	gotoxy(1,20);printf("FIN unetouche pour finir");
    	KM_WAIT_CHAR_s;
    }
    
    On exécute pour la 1ère fois avec un run"cubep1". Et la on voit un petit point clignoter su l'écran, il est donc en train de calculer les tableaux des Sin et Cos...
    et on attend, ... attend...,
    et oui c'est long !!
    Voici le temps que vas mettre le CPC à calculer ces tableaux :

    QUOI, il a mis presque 100 secondes à faire ce calcule !!!!
    Oui, on vas optimiser cela alors, d'une façon simple, on vas mettre toute les valeurs dans un fichier que l'on chargeras, cela iras bien plus vite.

    Pour l'affichage c'est pareil, on est très loin du temps réel :
      

    On voie bien sur les deux première images que l'on met presque 1,5 seconde pour faire le calcule pure, et 0,1 seconde pour effacer et afficher les points !
    Pour le calcule, on verra plus tard si on peut y faire quelque chose, on va déjà tenter d'optimiser le temps pour l'afficher.
    On commence par l'effacement de l'écran, on va utiliser un CLS qui utilise un détournement de l'utilisation de la pile pour aller plus vite. On ajoute donc la fonction suivante :
    // Efface l'ecran en utilisent la pile
    // détournéméne de la pile pour faire un cls super rapide !
    int PILE;
    void CLS_WidthPile()
    {
    __asm
           DI
           LD           (#_PILE),SP
           LD           B,#0
           LD           SP,#0 ; pile a 0 (car 0 - 1 = 0xFFFF fin de l ecran quand il est en 0xC000), comme cela on remonte jusqu a 0xC000
           LD           DE,#0
    BOUC:   PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           PUSH         DE
           DJNZ         BOUC
           LD           SP,(#_PILE)
    	   EI
           RET
    	   
    __endasm;
    }
    
    Et dans le fonction Afficher on retirer "// ON EFFACE TOUT " et on le remplace par CLS_WidthPile(); ce qui donne :
    void Afficher(unsigned char couleur)
    {
    	CLS_WidthPile();
    	
    	// On dessine 
    	// Que les point
    	DesPoint(couleur);
    }
    
    On va aussi optimiser le calcule des tableaux Sin Cos avec un chargement des valeurs, on fait un tit programme qui permet de les calculer et de les sauver (vous le trouverez dans le ZIP)
    et on modifie notre programme pour charger se fichier en y ajoutant une fonction de chargement de fichier ReadFileBin. On vas aussi utiliser directement la mémoire pour accédé au données des tableaux,
    donc modifier la déclaration de ceux ci par la création de pointeurs que l'on initialise dans la main.
    Tout ceci est fait dans le fichier cubep2.c qui se trouve dans le ZIP. Une fois compiler voyons ce que cela donne avec un run"cubep2.


    Donc pour les tables on passe de plus de 100 secondes à moins de 3 secondes, pas trop mal ;-)
    Et pour l'affichage :
      

    La on voir que pour l'affichage on passe de 0,1 seconde à 600 millièmes de seconde, belle progression.

    Il faudra voire pour optimiser un peut le calcule, mais on verras cela plus tard...

    Voila, comme d'hab, le tout se trouve dans se ZIP