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

📄 widget3d.c

📁 具有IDE功能的编辑器
💻 C
字号:
/* widget3d.c - draws a graphics box with a rotatable 3D object   Copyright (C) 1996-2000 Paul Sheer   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307, USA. */#include <config.h>#include <stdlib.h>#include <stdio.h>#include <X11/Intrinsic.h>#include <math.h>#include <my_string.h>#include "stringtools.h"#include "app_glob.c"#include "coolwidget.h"#include "widget3d.h"#include "vgagl.h"#include "3dkit.h"#ifdef USING_MATRIXLIB#include "matrix.h"#endif/* #define COLOR_3D_BACKGROUND (1*9 + 1*3 + 2) */#define COLOR_3D_BACKGROUND COLOR_FLAT#include "imagewidget.h"#include "mad.h"extern struct look *look;static Pixmap widget3d_currentpixmap;static long widget3d_thres;void destroy_solid (CWidget * w){    if (!w->solid)	return;    CClearAllSurfaces (w->ident);    if (w->solid->surf) {	free (w->solid->surf);	w->solid->surf = 0;    }    free (w->solid);    w->solid = 0;    if (w->gl_graphicscontext) {	free (w->gl_graphicscontext);	w->gl_graphicscontext = 0;    }}int eh_threed (CWidget * w, XEvent * xevent, CEvent * cwevent){    switch (xevent->type) {    case Expose:	render_3d_object (w, xevent->xexpose.x, xevent->xexpose.y, xevent->xexpose.width, xevent->xexpose.height);	break;    case ButtonRelease:    case ButtonPress:    case MotionNotify:	resolve_button (xevent, cwevent);	cwevent->x -= 2;	/*subtract border */	cwevent->y -= 2;	cwevent->ident = w->ident;	break;    }    return 0;}extern int override_8bit_non_lookup;void local_striangle (int x0, int y0,		      int x1, int y1,		      int x2, int y2, int z0, int bf){    long n;    XPoint p[3];    p[0].x = x0;    p[0].y = y0;    p[1].x = x1;    p[1].y = y1;    p[2].x = x2;    p[2].y = y2;    if ((((n = (x0 - x1) * (y0 - y2) - (y0 - y1) * (x0 - x2)) > 0) + bf) & 1 || bf == 2) {	if (abs (n) < widget3d_thres) {	    if (abs (x0) + abs (x1) + abs (x2) + abs (y0) + abs (y1) + abs (y2) < 32000) {		if (!override_8bit_non_lookup && CDepth >= 8 && (ClassOfVisual (CVisual) == PseudoColor || ClassOfVisual (CVisual) == StaticGray))		    CSetColor (z0);		else		    CSetColor (color_pixels[z0]);		XFillPolygon (CDisplay, widget3d_currentpixmap, CGC, p, 3, Convex, CoordModeOrigin);	    }	}    }}void local_drawline (int x1, int y1, int x2, int y2, int c){    CSetColor(c);    if(abs(x1) + abs(x2) + abs(y1) + abs(y2) < 32000)	    CLine(widget3d_currentpixmap, x1, y1, x2, y2);}void local_setpixel (int x, int y, int c){    CSetColor(c);    XDrawPoint(CDisplay, widget3d_currentpixmap, CGC, x, y);}/* this redraws the object. If force is non-zero then the object WILL   be redrawn. If not the routine checks if there are any events in the   event queue and only redraws if the event queue is empty. */CWidget *CRedraw3DObject (const char *ident, int force){    CWidget *w = CIdent (ident);    Window win = w->winid;    TD_Solid *object = w->solid;    if (force || !CCheckWindowEvent (win, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, 0)) {	gl_setcontext (w->gl_graphicscontext);	gl_enableclipping ();	widget3d_thres = w->width * w->height;	widget3d_currentpixmap = w->pixmap;	CSetColor (COLOR_3D_BACKGROUND);	CRectangle (widget3d_currentpixmap, 0, 0, w->width - 4, w->height - 4);	TD_draw_solid (object);	XCopyArea (CDisplay, widget3d_currentpixmap, win, CGC, 0, 0, w->width - 4, w->height - 4, 2, 2);    }    return w;}/* Allocates memory for the TD_Solid structure. returns 0 on error */TD_Solid *TD_allocate_solid (int max_num_surfaces){    TD_Solid *object;    if ((object = CMalloc (sizeof (TD_Solid))) == NULL)	return 0;    memset (object, 0, sizeof (TD_Solid));    object->num_surfaces = max_num_surfaces;    if ((object->surf = CMalloc (max_num_surfaces * sizeof (TD_Surface))) == NULL)	return 0;    memset (object->surf, 0, max_num_surfaces * sizeof (TD_Surface));    return object;}/*returns NULL on error, else returns a pointer to the surface points */TD_Surface *Calloc_surf (const char *ident, int surf_width, int surf_height, int *surf){    int j = 0;    CWidget *w = CIdent (ident);    for (; j < w->solid->num_surfaces; j++)	if (!w->solid->surf[j].point) {		/* find the first unused surface */	    if (surf)		*surf = j;	    w->solid->surf[j].point = CMalloc ((surf_width + 1) * (surf_height + 1) * sizeof (TD_Point));	    memset (w->solid->surf[j].point, 0, surf_width * surf_height * sizeof (TD_Point));	    w->solid->surf[j].w = surf_width;	    w->solid->surf[j].l = surf_height;	    return &(w->solid->surf[j]);	}    CError ("Max number of surfaces exceeded for this solid.\n");    return NULL;}/* free the i'th surface if widget ident */void Cfree_surf (CWidget *w, int i){    if(w->solid->surf[i].point) {	free(w->solid->surf[i].point);	w->solid->surf[i].point = NULL;    }}/* free the last surface of widget ident, returns first available surface in surf *//* returns 1 if there are any remaining unfree'd surfaces */int Cfree_last_surf (CWidget *w, int *surf){    int j = 0;    for (; j < w->solid->num_surfaces; j++)	if (!w->solid->surf[j].point)		/* find the first unused surface */	    break;    if (surf)	*surf = j;    if(j > 0)	Cfree_surf(w, --j);    if(j)	return 1;    return 0;}void CClearAllSurfaces(const char *ident){    CWidget *w = CIdent(ident);    while(Cfree_last_surf (w, NULL));}void CInitSurfacePoints (const char *ident, int width, int height, TD_Point data[]){    TD_Surface *s = Calloc_surf (ident, width, height, NULL);    memcpy (s->point, data, width * height * sizeof (TD_Point));    TD_initcolor (s, -256);}#ifdef USING_MATRIXLIBvoid CMatrixToSurface (const char *ident, int surf_width, int surf_height, Matrix * x, Matrix * offset, double scale){    TD_Point *p = CMalloc (x->columns * sizeof (TD_Point));    int i;    for (i = 0; i < x->columns; i++) {	p[i].x = (double) (Mard (*x, 0, i) + Mard (*offset, 0, 0)) * scale;	p[i].y = (double) (Mard (*x, 1, i) + Mard (*offset, 1, 0)) * scale;	p[i].z = (double) -(Mard (*x, 2, i) + Mard (*offset, 2, 0)) * scale;	p[i].dirx = 0;	p[i].diry = 0;	p[i].dirz = 0;    }    CInitSurfacePoints (ident, surf_width, surf_height, p);    free (p);}#endifCWidget * CDraw3DObject (const char *identifier, Window parent, int x, int y,	       int width, int height, int defaults, int max_num_surfaces){    int i, j, n = 0;    CWidget *w;    TD_Solid *object;    if (!(object = TD_allocate_solid (max_num_surfaces)))	CError ("Error allocating memeory in call to CDraw3DObject.\n");    width &= 0xFFFFFFFCUL;	/* width must be a multiple of 4 */    if (defaults) {	n = object->num_surfaces;	for (j = 0; j < n; j++) {	    object->surf[j].backfacing = 1;	/*don't draw any of surface that faces away */	    object->surf[j].depth_per_color = 6;	/*2^6 = 64 colors in the grey scale */	    object->surf[j].bitmap1 = NULL;	    object->surf[j].bitmap2 = NULL;	    object->surf[j].mesh_color = color_palette (6);	}	object->alpha = 0;	/* begin all at zero (flight dynamics */	object->beta = 0;	/* says plane is level */	object->gamma = 0;	object->xlight = -147;	/* lighting out of the screen,... */	object->ylight = -147;	/* ...to the right,... */	object->zlight = 147;	/* ...and from the top. */	object->distance = 85000;	/* distance of the camera from the */	/* origin */	object->x_cam = 85000;	object->y_cam = 0;	object->z_cam = 0;/* These two are scale factors for the screen: *//* xscale is now calculated so that the maximum volume (-2^15 to 2^15 or   -2^31 to 2^31) will just fit inside the screen width at this distance: */	object->yscale = object->xscale = (long) object->distance * (width + height) / (32768 * 4);/*to get display aspect square *//*The above gives an average (not to telescopic, and not to wide angle) view *//*use any triangle or linedrawing routine: */	object->draw_triangle = gl_triangle;	object->draw_striangle = local_striangle;	object->draw_wtriangle = gl_wtriangle;	object->draw_swtriangle = gl_swtriangle;	object->draw_line = local_drawline;	object->draw_point = local_setpixel;/* very important to set TDOPTION_INIT_ROTATION_MATRIX if you don't   calculate the rotation matrix yourself. */	object->option_flags = TDOPTION_INIT_ROTATION_MATRIX	    | TDOPTION_ALL_SAME_RENDER | TDOPTION_SORT_SURFACES	    | TDOPTION_ROTATE_OBJECT | TDOPTION_LIGHT_SOURCE_CAM	    | TDOPTION_FLAT_TRIANGLE;	object->render = TD_MESH_AND_SOLID;	/*how we want to render it */	object->posx = width / 2;	object->posy = height / 2;    }    w = CSetupWidget (identifier, parent, x, y,			  width + 4, height + 4, C_THREED_WIDGET, INPUT_MOTION, COLOR_3D_BACKGROUND, 1);    set_hint_pos (x + width + WIDGET_SPACING + 4, y + height + WIDGET_SPACING + 4);    w->eh = eh_threed;    w->solid = object;    w->destroy = destroy_solid;    w->pixmap = XCreatePixmap (CDisplay, CFirstWindow, width, height, CDepth);    if (defaults) {	for (j = 0; j < n; j++) {	    if (CDepth >= 8 && (ClassOfVisual (CVisual) == PseudoColor || ClassOfVisual (CVisual) == StaticGray)) {/*In this case only we can use the actual pixel values because the   triangle routines can write the calculated pixel values to the buffer   which will be the same as the actual (hardware interpreted) pixel values */		object->surf[j].shadow = color_grey (10);		object->surf[j].maxcolor = color_grey (61);	    } else {/*In all other cases, the triangle routine must calculate the color   and then convert it into a actual pixel value from the lookup   table. The triangle routine itself checks if   bytesperpixel is non-unity and performs lookup if so. */		object->surf[j].shadow = 43 + 10;		object->surf[j].maxcolor = 43 + 61;	    }	}    }/*now use vgagl graphics contexts */    gl_setcontextvirtual (width, height, (CDepth + 7) / 8,			  CDepth, 0);    w->gl_graphicscontext = CMalloc (sizeof (GraphicsContext));    gl_getcontext (w->gl_graphicscontext);    for(i=0;i<256;i++)	gl_trisetcolorlookup(i, color_pixels[i]);    CRedraw3DObject (identifier, 2);    return w;}void render_3d_object (CWidget *wdt, int x, int y, int rendw, int rendh){    int w = wdt->width;    int h = wdt->height;    Window win = wdt->winid;    int xim, yim, xwin, ywin;    xim = x - 2;    yim = y - 2;    xwin = x;    ywin = y;    if (xim < 0) {	rendw += xim;	xim = 0;	xwin = 2;    }    if (yim < 0) {	rendh += yim;	yim = 0;	ywin = 2;    }    XCopyArea(CDisplay, widget3d_currentpixmap, win, CGC, xim, yim, rendw, rendh, xwin, ywin);    render_bevel (win, 0, 0, w - 1, h - 1, 2, 1);}

⌨️ 快捷键说明

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