CODINGSDCC TUT'S PAR STEPHBB75 ★ 3D Tracé points ★

Sdcc - 17 - 3D - Trace PointsCoding Sdcc Tut's Par Stephbb75
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 :

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 écran 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

stephbb75

★ ANNÉE: 2013
★ AUTEUR: Stephbb75

Page précédente : Sdcc - 16 - 3D - Temps Reel Basic

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding » Sdcc - 06 - Lire un Fichier
» Coding » Sdcc - 02 - Utilisation de Sdcc
» Coding » Sdcc - 15 - Animation Par Sprite
» Coding » Sdcc - 05 - Ecrire du Text
» Coding » Sdcc - 12 - Put Pixel Tres Rapide
» Coding » Sdcc - 13 - Animation Par Couleur et Scrool
Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop
Page créée en 081 millisecondes et consultée 1962 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.