⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graph3d.c

📁 Microwindows genesis was with the NanoGUI project, and is now the primary distribution for both th
💻 C
字号:
/* * Copyright (c) 1999 Greg Haerr <greg@censoft.com> * * 3D Graphics Library for Micro-Windows */#define MWINCLUDECOLORS#include "windows.h"#include "device.h"#include "graph3d.h"#define USEBLIT		1	/* =1 to use memDC's*/static int	nxpix;static int	nypix;static vec1	xscale;static vec1	yscale;static vec3	eye;static vec3	direct;static double 	Q[5][5];static HDC	hdc;static HDC	hdcMem;static HBITMAP	hbmp, hbmpOrg;/* setup eye, direction, calc observation matrix Q*/voidlook3(vec1 x, vec1 y, vec1 z){	eye.x = x;	eye.y = y;	eye.z = z;	direct.x = -eye.x;	direct.y = -eye.y;	direct.z = -eye.z;	findQ();}voidinit3(HDC hDC, HWND memhwnd){	HBRUSH	hbr;	hdc = hDC;	if(hdc) {		nxpix = hdc->hwnd->clirect.right - hdc->hwnd->clirect.left;		nypix = hdc->hwnd->clirect.bottom - hdc->hwnd->clirect.top;		xscale = (vec1)(nxpix-1) / nxpix * nxpix/2;		yscale = (vec1)(nypix-1) / nypix * nypix/2;		if(memhwnd) {			hdcMem = CreateCompatibleDC(NULL);			if(hdcMem) {				hbmp = CreateCompatibleBitmap(hdcMem,					nxpix, nypix);				hbmpOrg = SelectObject(hdcMem, hbmp);				hdc = hdcMem;			}			hbr = (HBRUSH)GetClassLong(memhwnd, GCL_HBRBACKGROUND);			FillRect(hdc, NULL, hbr);		}		/* create pen for setcolor3() color override*/		SelectObject(hdc, CreatePen(PS_SOLID, 1, BLACK));	}}voidpaint3(HDC hDC){	if(hdcMem) {		BitBlt(hDC, 0, 0, nxpix, nypix, hdcMem, 0, 0, SRCCOPY);		DeleteObject(SelectObject(hdcMem, hbmpOrg));		DeleteDC(hdcMem);	}	hdcMem = NULL;}intfx(vec1 x){	return (int)(x * xscale + nxpix*0.5 - 0.5);}intfy(vec1 y){	return (int)(y * yscale + nypix*0.5 - 0.5);}voidmoveto3(vec2 pt){	MoveToEx(hdc, fx(pt.x), fy(pt.y), NULL);}voidsetcolor3(MWCOLORVAL c){	if(hdc)		hdc->pen->color = c;}voidlineto3(vec2 pt){	LineTo(hdc, fx(pt.x), fy(pt.y));}voidpolyfill(int n, vec2 points[]){	int	i;	int	xoff, yoff;	MWPOINT	pv[MAXPOLY];	if(!hdc)		return;	/* calc window offset*/	xoff = hdc->hwnd->clirect.left;	yoff = hdc->hwnd->clirect.top;	/* only plot non-trivial polygons*/	if(n > 2) {		for(i=0; i<n; ++i) {			pv[i].x = fx(points[i].x) + xoff;			pv[i].y = fy(points[i].y) + yoff;			/* fix: floating round error, y intercept difference			 * with GdLine			 */			/*pv[i].x = fx(points[i].x + xoff);*/			/*pv[i].y = fy(points[i].y + yoff);*/		}		GdSetForeground(GdFindColor(hdc->pen->color));		GdFillPoly(hdc->psd, n, pv);	}}voidsquare(void){	vec2	pt0, pt1, pt2, pt3;	pt0.x = -1; pt0.y = 1;	pt1.x = -1; pt1.y = -1;	pt2.x = 1; pt2.y = -1;	pt3.x = 1; pt3.y = 1;	moveto3(pt0);	lineto3(pt1);	lineto3(pt2);	lineto3(pt3);	lineto3(pt0);}voidcircle3(vec1 r){	vec1 	theta = 0;	vec1	thinc = 2*pi/100;	int 	i;	vec2	pt;	pt.x = r;	pt.y = 0.0;	moveto3(pt);	for(i=0; i<100; ++i) {		theta = theta + thinc;		pt.x = r*cos(theta);		pt.y = r*sin(theta);		lineto3(pt);	}}voiddaisy(vec1 r,int points){	int	i, j;	vec1	theta = 0;	vec1	thinc;	vec2	pt[100];	/* calculate n points on a circle*/	thinc = 2*pi/points;	for(i=0; i<points; ++i) {		pt[i].x = r*cos(theta);		pt[i].y = r*sin(theta);		theta += thinc;	}	/* join point i to point j for all 0 <= i < j < n */	for(i=0; i<points-1; ++i) {		for(j=i+1; j<points; ++j) {			moveto3(pt[i]);			lineto3(pt[j]);		}	}}voidrose(vec1 r,int levels,int points){	int	i, j, m, n;	vec1	r1, theta, thinc;	vec2	inner[100];	vec2	outer[100];	vec2	triangle[3];	m = levels;	n = points;	thinc = 2*pi/n;	/* initial inner circle*/	for(i=0; i<n; ++i) {		inner[i].x = 0.0;		inner[i].y = 0.0;	}	/* loop thru m levels*/	for(j=1; j<=m; ++j) {		theta = -j*pi/n;		r1 = r * (vec1)j/m;		/* calc n points on outer circle*/		for(i=0; i<n; ++i) {			theta += thinc;			outer[i].x = r1*cos(theta);			outer[i].y = r1*sin(theta);		}		/* construct/draw triangles with vertices on		 * inner and outer circles		 */		for(i=0; i<n; ++i) {			triangle[0] = outer[i];			triangle[1] = outer[(i+1) % n];			triangle[2] = inner[i];			/* fill triangle in red*/			setcolor3(RED);			polyfill(3, triangle);#if 1			/* outline triangle in white*/			setcolor3(WHITE);			moveto3(triangle[0]);			lineto3(triangle[1]);			lineto3(triangle[2]);			lineto3(triangle[0]);#endif		}		/* copy points on outer circle to inner arrays*/		for(i=0; i<n; ++i)			inner[i] = outer[i];	}}/* draw a triangle with cordners v0, v1, v2*/voidtriangle(vec2 v0, vec2 v1, vec2 v2){	vec2	poly[3];	poly[0] = v0;	poly[1] = v1;	poly[2] = v2;	setcolor3(GREEN);	polyfill(3, poly);	setcolor3(BLACK);	moveto3(poly[2]);	lineto3(poly[0]);	lineto3(poly[1]);	lineto3(poly[2]);}/* draw a quadrilateral with corners v0, v1, v2, v3*/voidquadrilateral(vec2 v0, vec2 v1, vec2 v2, vec2 v3){	vec2	poly[4];	poly[0] = v0;	poly[1] = v1;	poly[2] = v2;	poly[3] = v3;	setcolor3(GREEN);	polyfill(4, poly);	setcolor3(BLACK);	moveto3(poly[3]);	lineto3(poly[0]);	lineto3(poly[1]);	lineto3(poly[2]);	lineto3(poly[3]);}/* find intersection of lines v0 to v1 and v2 to v3*/static intpatch(vec2 v0, vec2 v1, vec2 v2, vec2 v3){	vec1	denom;	vec1	mu;	vec2	v4;	denom = (v1.x-v0.x)*(v3.y-v2.y) - (v1.y-v0.y)*(v3.x-v2.x);	if(fabs(denom) > epsilon) {		mu = ((v2.x-v0.x)*(v3.y-v2.y) - (v2.y-v0.y)*(v3.x-v2.x))/denom;		/* if intersection between lines v0 to v1 and v2 to v3,		 * call it v4 and form triangles v0,v2,v4 and v1,v3,v4		 */		if(mu >= 0 && mu <= 1) {			v4.x = (1-mu)*v0.x + mu*v1.x;			v4.y = (1-mu)*v0.y + mu*v1.y;			triangle(v0, v2, v4);			triangle(v1, v3, v4);			return 0;		}	}	/* else find intersection of lines v0 to v2 and v1 to v3*/	denom = (v2.x-v0.x)*(v3.y-v1.y) - (v2.y-v0.y)*(v3.x-v1.x);	if(fabs(denom) > epsilon) {		mu = ((v1.x-v0.x)*(v3.y-v1.y) - (v1.y-v0.y)*(v3.x-v1.x))/denom;		/* if intersection between v0 and v1, call it v4		 * and form triangles v0,v1,v4 and v2,v3,v4		 */		if(mu >= 0 && mu <= 1) {			v4.x = (1-mu)*v0.x + mu*v2.x;			v4.y = (1-mu)*v0.y + mu*v2.y;			triangle(v0, v1, v4);			triangle(v2, v3, v4);			return 0;		}	}	/* there are no proper intersections so form quadrilateral v0,v1,v3,v2*/	quadrilateral(v0, v1, v3, v2);	return 1;}/* plotted function*/static vec1plotfn(vec1 x, vec1 z){	vec1	t;	/* y = 4sin(sqrt(x*x+z*z))/sqrt(x*x+z*z) */	t = sqrt(x*x + z*z);	if(fabs(t) < epsilon)		return 4.0;	return 4.0 * sin(t) / t;}/* draw mathematical function plotfn*/voiddrawgrid(vec1 xmin, vec1 xmax, int nx, vec1 zmin, vec1 zmax, int nz){	int	i, j;	vec1	xi, xstep, yij;	vec1	zj, zstep;	vec2	v[2][100];	double	S[5][5];	/* scale it down*/	scale3(1.0/(xmax-xmin)*2, 1.0/(xmax-xmin)*2, 1.0/(zmax-zmin), S);	mult3(Q, S, Q);	/* grid from xmin to xmax in nx steps and zmin to xmax in nz steps*/	xstep = (xmax-xmin)/nx;	zstep = (zmax-zmin)/nz;	xi = xmin;	zj = zmin;	/* calc grid points on first fixed-z line, fine the y-height	 * and transfrorm the points (xi,yij,zj) into observed	 * position.  Observed first set stored in v[0,1..nx]	 */	for(i=0; i<=nx; ++i) {		yij = plotfn(xi, zj);		v[0][i].x = Q[1][1]*xi + Q[1][2]*yij + Q[1][3]*zj;		v[0][i].y = Q[2][1]*xi + Q[2][2]*yij + Q[2][3]*zj;		xi += xstep;	}	/* run thru consecutive fixed-z lines (the second set)*/	for(j=0; j<nz; ++j) {		xi = xmin;		zj += zstep;		/* calc grid points on this second set, find the		 * y-height and transform the points (xi,yij,zj)		 * into observed position.  Observed second set		 * stored in v[1,0..nx]		 */		for(i=0; i<=nx; ++i) {			yij = plotfn(xi, zj);			v[1][i].x = Q[1][1]*xi + Q[1][2]*yij + Q[1][3]*zj;			v[1][i].y = Q[2][1]*xi + Q[2][2]*yij + Q[2][3]*zj;			xi += xstep;		}		/* run thru the nx patches formed by these two sets*/		for(i=0; i<nx; ++i)			patch(v[0][i], v[0][i+1], v[1][i], v[1][i+1]);		/* copy second set into first set*/		for(i=0; i<=nx; ++i)			v[0][i] = v[1][i];	}}/* returns the angle whose tangent is y/x. * all anomalies such as x=0 are also checked */vec1angle(vec1 x, vec1 y){	if(fabs(x) < epsilon)		if(fabs(y) < epsilon)			return 0.0;		else 			if(y > 0.0)				return pi*0.5;			else return pi*1.5;	else		if(x < 0.0)			return atan(y/x) + pi;		else return atan(y/x);}/* calc 3d scaling matrix A giving scaling vector sx,sy,sz. * one unit on the x axis becomes sx units, one unit on y, sy, * and one unit on the z axis becomes sz units */voidscale3(vec1 sx, vec1 sy, vec1 sz, double A[][5]){	int	i, j;	for(i=1; i<5; ++i)		for(j=1; j<5; ++j)			A[i][j] = 0.0;	A[1][1] = sx;	A[2][2] = sy;	A[3][3] = sz;	A[4][4] = 1.0;}/* calc 3d axes translation matrix A * origin translated by vectdor tx,ty,tz */voidtran3(vec1 tx, vec1 ty, vec1 tz, double A[][5]){	int	i, j;	for(i=1; i<5; ++i) {		for(j=1; j<5; ++j)			A[i][j] = 0.0;		A[i][i] = 1.0;	}	A[1][4] = -tx;	A[2][4] = -ty;	A[3][4] = -tz;}/* calc 3d axes rotation matrix A.  The axes are * rotated anti-clockwise through an angle theta radians * about an axis specified by m: m=1 means x, m=2 y, m=3 z axis */voidrot3(int m, vec1 theta, double A[][5]){	int	i, j, m1, m2;	vec1	c, s;	for(i=1; i<5; ++i) 		for(j=1; j<5; ++j)			A[i][j] = 0.0;	A[m][m] = 1.0;	A[4][4] = 1.0;	m1 = (m % 3) + 1;	m2 = (m1 % 3) + 1;	c = cos(theta);	s = sin(theta);	A[m1][m1] = c;	A[m2][m2] = c;	A[m1][m2] = s;	A[m2][m1] = s;}/* calc the matrix product C of two matrices A and B*/voidmult3(double A[][5], double B[][5], double C[][5]){	int	i, j, k;	vec1	ab;	for(i=1; i<5; ++i) 		for(j=1; j<5; ++j) {			ab = 0;			for(k=1; k<5; ++k)				ab += A[i][k] * B[k][j];			C[i][j] = ab;		}}/* calc observation matrix Q for given observer*/voidfindQ(void){	vec1	alpha, beta, gamma, v, w;	double	E[5][5];	double	F[5][5];	double	G[5][5];	double	H[5][5];	double	U[5][5];	/* calc translation matrix F*/	tran3(eye.x, eye.y, eye.z, F);	/* calc rotation matrix G*/	alpha = angle(-direct.x, -direct.y);	rot3(3, alpha, G);	/* calc rotation matrix H*/	v = sqrt(direct.x*direct.x + direct.y*direct.y);	beta = angle(-direct.z, v);	rot3(2, beta, H);	/* calc rotation matrix U*/	w = sqrt(v*v + direct.z*direct.z);	gamma = angle(-direct.x*w, direct.y*direct.z);	rot3(3, -gamma, U);	/* combine the transformations to find Q*/	mult3(G, F, Q);	mult3(H, Q, E);	mult3(U, E, Q);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -