1 /*
2  * Compiz cube model plugin
3  *
4  * cubemodel.c
5  *
6  * This plugin displays wavefront (.obj) 3D mesh models inside of
7  * the transparent cube.
8  *
9  * Copyright : (C) 2008 by David Mikos
10  * E-mail    : infiniteloopcounter@gmail.com
11  *
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  */
24 
25 /*
26  * Model loader code based on cubemodel/cubefx plugin "cubemodelModel.c.in"
27  * code - originally written by Joel Bosvel (b0le).
28  */
29 
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <signal.h>
34 #include <unistd.h>
35 #include <math.h>
36 
37 #include "cubemodel-internal.h"
38 #include "cubemodel_options.h"
39 
40 int cubemodelDisplayPrivateIndex;
41 int cubeDisplayPrivateIndex;
42 
43 static void
initWorldVariables(CompScreen * s)44 initWorldVariables (CompScreen *s)
45 {
46     CUBEMODEL_SCREEN (s);
47     CUBE_SCREEN (s);
48 
49     cms->hsize = s->hsize * cs->nOutput;
50 
51     cms->arcAngle = 360.0f / cms->hsize;
52     cms->radius = cs->distance / cosf (0.5 * (cms->arcAngle * toRadians));
53     cms->topDistance = cs->distance;
54 
55     if (cubemodelGetRescaleWidth (s))
56 	cms->ratio = (float) s->width / (float) s->height;
57     else
58 	cms->ratio = 1;
59 
60     cms->sideDistance = cms->topDistance * cms->ratio;
61 }
62 
63 static void
updateModel(CompScreen * s,int start,int end)64 updateModel (CompScreen *s,
65 	     int        start,
66 	     int        end)
67 {
68     int           i;
69     CompListValue *modelScale         = cubemodelGetModelScaleFactor (s);
70     CompListValue *modelX             = cubemodelGetModelXOffset (s);
71     CompListValue *modelY             = cubemodelGetModelYOffset (s);
72     CompListValue *modelZ             = cubemodelGetModelZOffset (s);
73     CompListValue *modelRotationPlane = cubemodelGetModelRotationPlane (s);
74     CompListValue *modelRotationRate  = cubemodelGetModelRotationRate (s);
75     CompListValue *modelAnimation     = cubemodelGetModelAnimation (s);
76     CompListValue *modelFps           = cubemodelGetModelFps (s);
77 
78     CUBEMODEL_SCREEN (s);
79 
80     start = MAX (start, 0);
81     end   = MIN (end, cms->numModels);
82 
83     for (i = start; i< end; i++)
84     {
85 	if (!cms->models[i] || !cms->models[i]->finishedLoading)
86 	    continue;
87 
88 	if (modelScale->nValue > i)
89 	    cms->models[i]->scaleGlobal = modelScale->value[i].f;
90 
91 	if (modelX->nValue > i)
92 	    cms->models[i]->translate[0] = modelX->value[i].f * cms->ratio;
93 	if (modelY->nValue > i)
94 	    cms->models[i]->translate[1] = modelY->value[i].f;
95 	if (modelZ->nValue > i)
96 	    cms->models[i]->translate[2] = modelZ->value[i].f * cms->ratio;
97 
98 	if (modelRotationPlane->nValue > i)
99 	{
100 	    int rot = modelRotationPlane->value[i].i;
101 
102 	    switch (rot % 3) {
103 	    case 0:
104 		cms->models[i]->rotate[1] = 0;
105 		cms->models[i]->rotate[2] = 1;
106 		cms->models[i]->rotate[3] = 0;
107 	    	break;
108 	    case 1:
109 		cms->models[i]->rotate[1] = 1;
110 		cms->models[i]->rotate[2] = 0;
111 		cms->models[i]->rotate[3] = 0;
112 	    	break;
113 	    case 2:
114 		cms->models[i]->rotate[1] = 0;
115 		cms->models[i]->rotate[2] = 0;
116 		cms->models[i]->rotate[3] = 1;
117 	    	break;
118 	    }
119 
120 	    if (rot / 3 != 0)
121 	    {
122 		cms->models[i]->rotate[1] *= -1;
123 		cms->models[i]->rotate[2] *= -1;
124 		cms->models[i]->rotate[3] *= -1;
125 	    }
126 
127 	}
128 	if (modelRotationRate->nValue > i)
129 	    cms->models[i]->rotateSpeed = modelRotationRate->value[i].f;
130 
131 	if (modelFps->nValue > i)
132 	{
133 	    cms->models[i]->fps = modelFps->value[i].i;
134 
135 	    if (modelAnimation->nValue > i && modelAnimation->value[i].i == 2)
136 		cms->models[i]->fps *= -1;
137 	}
138     }
139 }
140 
141 static void
initCubemodel(CompScreen * s)142 initCubemodel (CompScreen *s)
143 {
144     int   i, numModels;
145     float translate[] = { 0, 0, 0 };
146     float rotate[]    = { 0, 0, 0, 0 };
147     float scale[]     = { 1, 1, 1, 1 };
148     float color[]     = { 1, 1, 1, 1 };
149     float rotateSpeed = 0;
150     Bool  status, animation = FALSE;
151     int   fps = 3;
152 
153     CUBEMODEL_SCREEN (s);
154 
155     CompListValue * modelFilename      = cubemodelGetModelFilename (s);
156     CompListValue * modelScale         = cubemodelGetModelScaleFactor (s);
157     CompListValue * modelX             = cubemodelGetModelXOffset (s);
158     CompListValue * modelY             = cubemodelGetModelYOffset (s);
159     CompListValue * modelZ             = cubemodelGetModelZOffset (s);
160     CompListValue * modelRotationPlane = cubemodelGetModelRotationPlane (s);
161     CompListValue * modelRotationRate  = cubemodelGetModelRotationRate (s);
162     CompListValue * modelAnimation     = cubemodelGetModelAnimation (s);
163     CompListValue * modelFps           = cubemodelGetModelFps (s);
164 
165     numModels = modelFilename->nValue;
166 
167     if (modelScale->nValue < numModels)
168 	numModels = modelScale->nValue;
169 
170     if (modelX->nValue < numModels)
171 	numModels = modelX->nValue;
172     if (modelY->nValue < numModels)
173 	numModels = modelY->nValue;
174     if (modelZ->nValue < numModels)
175 	numModels = modelZ->nValue;
176     if (modelRotationPlane->nValue < numModels)
177 	numModels = modelRotationPlane->nValue;
178     if (modelRotationRate->nValue < numModels)
179 	numModels = modelRotationRate->nValue;
180     if (modelAnimation->nValue < numModels)
181 	numModels = modelAnimation->nValue;
182     if (modelFps->nValue < numModels)
183 	numModels = modelFps->nValue;
184 
185     cms->numModels = numModels;
186     cms->modelFilename = malloc (numModels * sizeof(char *));
187 
188     cms->models = malloc (numModels * sizeof (CubemodelObject *));
189 
190     for (i = 0; i < numModels; i++)
191 	cms->models[i] = NULL;
192 
193     for (i = 0; i < numModels; i++)
194     {
195 	cms->models[i] = malloc (sizeof (CubemodelObject));
196 	if (!cms->models[i])
197 	    break;
198 
199 	animation = FALSE;
200 	if (modelAnimation->value[i].i > 0)
201 	    animation = TRUE;
202 
203 	status = FALSE;
204 
205 	if (modelFilename->nValue > i)
206 	    status = cubemodelAddModelObject (s, cms->models[i],
207 					      modelFilename->value[i].s,
208 					      translate, rotate,
209 					      rotateSpeed, scale,
210 					      color, animation, fps);
211 
212 	if (!status)
213 	    cms->modelFilename[i] = NULL;
214 	else
215 	    cms->modelFilename[i] = strdup (modelFilename->value[i].s);
216     }
217 
218     updateModel (s, 0, cms->numModels);
219 
220     initWorldVariables (s);
221 }
222 
223 static void
freeCubemodel(CompScreen * s)224 freeCubemodel (CompScreen *s)
225 {
226     CUBEMODEL_SCREEN (s);
227 
228     int i;
229 
230     if (cms->models)
231     {
232 	for (i = 0; i < cms->numModels; i++)
233 	{
234 	    if (cms->models[i])
235 	    {
236 		cubemodelDeleteModelObject (s, cms->models[i]);
237 		free (cms->models[i]);
238 	    }
239 	}
240 	free (cms->models);
241     }
242 
243     if (cms->modelFilename)
244     {
245 	for (i = 0; i < cms->numModels; i++)
246 	{
247 	    if (cms->modelFilename[i])
248 		free (cms->modelFilename[i]);
249 	}
250 
251 	free (cms->modelFilename);
252     }
253 }
254 
255 static void
updateCubemodel(CompScreen * s)256 updateCubemodel (CompScreen *s)
257 {
258     freeCubemodel (s);
259     initCubemodel (s);
260 }
261 
262 static void
cubemodelLoadingOptionChange(CompScreen * s,CompOption * opt,CubemodelScreenOptions num)263 cubemodelLoadingOptionChange (CompScreen             *s,
264 			      CompOption             *opt,
265 			      CubemodelScreenOptions num)
266 {
267     int           i, numModels, fps = 3;
268     CompListValue *modelFilename, *modelAnimation;
269     float         translate[] = { 0, 0, 0 };
270     float         rotate[]    = { 0, 0, 0, 0 };
271     float         scale[]     = { 1, 1, 1, 1 };
272     float         color[]     = { 1, 1, 1, 1 };
273     float         rotateSpeed = 0;
274 
275     CUBEMODEL_SCREEN (s);
276 
277     modelFilename  = cubemodelGetModelFilename (s);
278     modelAnimation = cubemodelGetModelAnimation (s);
279     numModels      = modelAnimation->nValue;
280 
281     if (modelAnimation->nValue < numModels)
282 	numModels = modelAnimation->nValue;
283 
284     if (!cms->models || cms->numModels <= 0 || !cms->modelFilename)
285     {
286 	updateCubemodel (s);
287 	return;
288     }
289 
290 
291     if (numModels != cms->numModels)
292     {
293 	for (i = numModels; i < cms->numModels; i++)
294 	{
295 	    cubemodelDeleteModelObject (s, cms->models[i]);
296 
297 	    if (cms->modelFilename[i])
298 		free (cms->modelFilename[i]);
299 	    if (cms->models[i])
300 		free (cms->models[i]);
301 	}
302 
303 	cms->modelFilename = realloc (cms->modelFilename,
304 				      numModels * sizeof (char *));
305 	cms->models        = realloc (cms->models,
306 				      numModels * sizeof (CubemodelObject *));
307 
308 	for (i = cms->numModels; i < numModels; i++)
309 	{
310 	    cms->modelFilename[i] = NULL;
311 	    cms->models[i] = malloc (sizeof (CubemodelObject));
312 	}
313 
314 	cms->numModels = numModels;
315     }
316 
317     for (i = 0; i < numModels; i++)
318     {
319 	Bool animation, fileDiff = TRUE;
320 
321 	if (!modelFilename->value)
322 	    continue;
323 
324 	if (modelFilename->nValue <= i)
325 	    continue;
326 
327 	if (!cms->modelFilename[i] && !modelFilename->value[i].s)
328 	    continue;
329 
330 	if (cms->modelFilename[i] && modelFilename->value[i].s)
331 	    fileDiff = strcmp (cms->modelFilename[i],
332 			       modelFilename->value[i].s);
333 
334 	animation = (modelAnimation->value[i].i > 0);
335 
336 	if (animation != cms->models[i]->animation || fileDiff)
337 	{
338 	    Bool status;
339 
340 	    cubemodelDeleteModelObject (s, cms->models[i]);
341 	    if (cms->modelFilename[i])
342 		free (cms->modelFilename[i]);
343 
344 	    status = cubemodelAddModelObject (s, cms->models[i],
345 					      modelFilename->value[i].s,
346 					      translate, rotate, rotateSpeed,
347 					      scale, color, animation, fps);
348 	    if (!status)
349 		cms->modelFilename[i] = NULL;
350 	    else
351 		cms->modelFilename[i] = strdup (modelFilename->value[i].s);
352 	}
353     }
354 
355     updateModel (s, 0, cms->numModels);
356 }
357 
358 static void
cubemodelModelOptionChange(CompScreen * s,CompOption * opt,CubemodelScreenOptions num)359 cubemodelModelOptionChange (CompScreen             *s,
360 			    CompOption             *opt,
361 			    CubemodelScreenOptions num)
362 {
363     CUBEMODEL_SCREEN (s);
364 
365     if (!cms->models || cms->numModels <= 0)
366     {
367 	updateCubemodel (s);
368 	return;
369     }
370 
371     updateModel (s, 0, cms->numModels);
372 }
373 
374 
375 static void
cubemodelClearTargetOutput(CompScreen * s,float xRotate,float vRotate)376 cubemodelClearTargetOutput (CompScreen *s,
377 			    float      xRotate,
378 			    float      vRotate)
379 {
380     CUBEMODEL_SCREEN (s);
381     CUBE_SCREEN (s);
382 
383     UNWRAP (cms, cs, clearTargetOutput);
384     (*cs->clearTargetOutput) (s, xRotate, vRotate);
385     WRAP (cms, cs, clearTargetOutput, cubemodelClearTargetOutput);
386 
387     glClear (GL_DEPTH_BUFFER_BIT);
388 }
389 
390 static void
setLightPosition(CompScreen * s,GLenum light)391 setLightPosition (CompScreen *s,
392 		  GLenum     light)
393 {
394     float angle = cubemodelGetLightInclination (s) * toRadians;
395     float position[] = { 0.0, 0.0, 1.0, 0.0 };
396 
397     if (cubemodelGetRotateLighting (s))
398 	angle = 0;
399 
400     position[1] = sinf (angle);
401     position[2] = cosf (angle);
402 
403     glLightfv (light, GL_POSITION, position);
404 }
405 
406 static void
cubemodelPaintInside(CompScreen * s,const ScreenPaintAttrib * sAttrib,const CompTransform * transform,CompOutput * output,int size)407 cubemodelPaintInside (CompScreen              *s,
408                       const ScreenPaintAttrib *sAttrib,
409                       const CompTransform     *transform,
410                       CompOutput              *output,
411                       int                     size)
412 {
413     int                i;
414     static const float matShininess[] = { 60.0 };
415     static const float matSpecular[] = { 0.6, 0.6, 0.6, 1.0 };
416     static const float matDiffuse[] = { 1.0, 1.0, 1.0, 1.0 };
417     static const float matAmbient[] = { 0.8, 0.8, 0.9, 1.0 };
418 
419     static const float lmodelLocalviewer[] = { 0.0 };
420     static       float lmodelTwoside[] = { 0.0 };
421     static       float lmodelAmbient[] = { 0.4, 0.4, 0.4, 0.4 };
422     static       float lmodelDiffuse[] = { 1.0, 1.0, 1.0, 1.0 };
423     static       float lmodelSpecular[]= { 0.6, 0.6, 0.6, 0.6 };
424 
425     ScreenPaintAttrib  sA = *sAttrib;
426     CompTransform      mT = *transform;
427     Bool               enabledCull;
428     int                cull;
429     float              scale, outputRatio = 1.0f;
430 
431     CUBEMODEL_SCREEN (s);
432     CUBE_SCREEN (s);
433 
434     if (cms->hsize != s->hsize * cs->nOutput)
435     {
436 	initWorldVariables (s);
437 	updateModel (s, 0, cms->numModels);
438     }
439 
440     sA.yRotate += cs->invert * (360.0f / size) *
441 		  (cs->xRotations - (s->x* cs->nOutput));
442 
443     (*s->applyScreenTransform) (s, &sA, output, &mT);
444 
445     glPushMatrix ();
446 
447     if (cubemodelGetRotateLighting (s))
448 	setLightPosition (s, GL_LIGHT1);
449 
450     glLoadMatrixf (mT.m);
451 
452     if (!cubemodelGetRotateLighting (s))
453 	setLightPosition (s, GL_LIGHT1);
454 
455 
456     glTranslatef (cs->outputXOffset, -cs->outputYOffset, 0.0f);
457     glScalef (cs->outputXScale, cs->outputYScale, 1.0f);
458 
459     glPushAttrib (GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT |
460 		  GL_LIGHTING_BIT     | GL_DEPTH_BUFFER_BIT);
461 
462     glEnable (GL_BLEND);
463     glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
464 
465     lmodelAmbient[0]  = cubemodelGetLightAmbient (s);
466     lmodelDiffuse[0]  = cubemodelGetLightDiffuse (s);
467     lmodelSpecular[0] = cubemodelGetLightSpecular (s);
468 
469     for (i = 1; i < 4; i++)
470     {
471 	lmodelAmbient[i]  = lmodelAmbient[0];
472 	lmodelDiffuse[i]  = lmodelDiffuse[0];
473 	lmodelSpecular[i] = lmodelSpecular[0];
474     }
475 
476     lmodelTwoside[0] = (cubemodelGetRenderFrontAndBack (s) ? 1.0f : 0.0f);
477 
478 
479     glLightModelfv (GL_LIGHT_MODEL_LOCAL_VIEWER, lmodelLocalviewer);
480     glLightModelfv (GL_LIGHT_MODEL_TWO_SIDE, lmodelTwoside);
481     glLightModelfv (GL_LIGHT_MODEL_AMBIENT,  lmodelAmbient);
482     glLightfv (GL_LIGHT1, GL_DIFFUSE,   lmodelDiffuse);
483     glLightfv (GL_LIGHT1, GL_SPECULAR,  lmodelSpecular);
484 
485     enabledCull = glIsEnabled (GL_CULL_FACE);
486 
487     glGetIntegerv (GL_CULL_FACE_MODE, &cull);
488     glEnable (GL_CULL_FACE);
489 
490     glCullFace (~cull & (GL_FRONT | GL_BACK));
491     glCullFace (cull);
492 
493     glPushMatrix ();
494 
495     glColor4usv (defaultColor);
496 
497     glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, matShininess);
498     glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, matSpecular);
499     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, matDiffuse);
500     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, matAmbient);
501 
502     glEnable (GL_NORMALIZE);
503     glEnable (GL_DEPTH_TEST);
504     glEnable (GL_COLOR_MATERIAL);
505     glEnable (GL_LIGHTING);
506     glEnable (GL_LIGHT1);
507     glDisable (GL_LIGHT0);
508 
509     glDepthFunc (GL_LEQUAL); /* for transparency maps */
510     glShadeModel(GL_SMOOTH);
511 
512     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
513 
514     scale = cs->distance;
515 
516     if (cubemodelGetRescaleWidth (s))
517     {
518 	if (cs->moMode == CUBE_MOMODE_AUTO && cs->nOutput < s->nOutputDev)
519 	    outputRatio = (float) s->width / (float) s->height;
520 	else
521 	    outputRatio = (float) output->width / (float) output->height;
522     }
523 
524     glScalef (scale / outputRatio, scale, scale / outputRatio);
525 
526     glPushMatrix ();
527 
528     glColor4f (1.0, 1.0, 1.0, 1.0);
529 
530     for (i = 0; i < cms->numModels; i++)
531     {
532 	glPushMatrix ();
533 	cubemodelDrawModelObject (s, cms->models[i],
534 	                          cubemodelGetGlobalModelScaleFactor (s));
535 	glPopMatrix ();
536 
537     }
538     glPopMatrix ();
539 
540     glPopMatrix ();
541 
542     glDisable (GL_LIGHT1);
543     glDisable (GL_NORMALIZE);
544 
545     if (!s->lighting)
546 	glDisable (GL_LIGHTING);
547 
548     glDisable (GL_DEPTH_TEST);
549 
550     if (enabledCull)
551 	glDisable (GL_CULL_FACE);
552 
553     glPopMatrix ();
554 
555     glPopAttrib ();
556 
557     cms->damage = TRUE;
558 
559     UNWRAP (cms, cs, paintInside);
560     (*cs->paintInside) (s, sAttrib, transform, output, size);
561     WRAP (cms, cs, paintInside, cubemodelPaintInside);
562 }
563 
564 static void
cubemodelPreparePaintScreen(CompScreen * s,int ms)565 cubemodelPreparePaintScreen (CompScreen *s,
566 			     int        ms)
567 {
568     int i;
569 
570     CUBEMODEL_SCREEN (s);
571 
572     for (i = 0; i < cms->numModels; i++)
573     {
574 	if (!cms->models[i]->finishedLoading)
575 	    continue;
576 
577 	if (cms->models[i]->updateAttributes)
578 	{
579 	    updateModel (s, i, i + 1);
580 	    cms->models[i]->updateAttributes = FALSE;
581 	}
582 
583 	cubemodelUpdateModelObject (s, cms->models[i],  ms / 1000.0f);
584     }
585 
586     UNWRAP (cms, s, preparePaintScreen);
587     (*s->preparePaintScreen) (s, ms);
588     WRAP (cms, s, preparePaintScreen, cubemodelPreparePaintScreen);
589 }
590 
591 static void
cubemodelDonePaintScreen(CompScreen * s)592 cubemodelDonePaintScreen (CompScreen *s)
593 {
594     CUBEMODEL_SCREEN (s);
595 
596     if (cms->damage)
597     {
598 	damageScreen (s);
599 	cms->damage = FALSE;
600     }
601 
602     UNWRAP (cms, s, donePaintScreen);
603     (*s->donePaintScreen) (s);
604     WRAP (cms, s, donePaintScreen, cubemodelDonePaintScreen);
605 }
606 
607 static Bool
cubemodelInitDisplay(CompPlugin * p,CompDisplay * d)608 cubemodelInitDisplay (CompPlugin  *p,
609 		      CompDisplay *d)
610 {
611     CubemodelDisplay *cmd;
612 
613     if (!checkPluginABI ("core", CORE_ABIVERSION)
614 	|| !checkPluginABI ("cube", CUBE_ABIVERSION))
615 	return FALSE;
616 
617     if (!getPluginDisplayIndex (d, "cube", &cubeDisplayPrivateIndex))
618 	return FALSE;
619 
620     cmd = malloc (sizeof (CubemodelDisplay));
621     if (!cmd)
622 	return FALSE;
623 
624     cmd->screenPrivateIndex = allocateScreenPrivateIndex (d);
625     if (cmd->screenPrivateIndex < 0)
626     {
627 	free (cmd);
628 	return FALSE;
629     }
630 
631     d->base.privates[cubemodelDisplayPrivateIndex].ptr = cmd;
632 
633     return TRUE;
634 }
635 
636 static void
cubemodelFiniDisplay(CompPlugin * p,CompDisplay * d)637 cubemodelFiniDisplay (CompPlugin  *p,
638 		      CompDisplay *d)
639 {
640     CUBEMODEL_DISPLAY (d);
641 
642     freeScreenPrivateIndex (d, cmd->screenPrivateIndex);
643     free (cmd);
644 }
645 
646 static Bool
cubemodelInitScreen(CompPlugin * p,CompScreen * s)647 cubemodelInitScreen (CompPlugin *p,
648 		CompScreen *s)
649 {
650     static const float ambient[]  = { 0.0, 0.0, 0.0, 0.0 };
651     static const float diffuse[]  = { 1.0, 1.0, 1.0, 1.0 };
652     static const float specular[] = { 0.6, 0.6, 0.6, 1.0 };
653 
654     CubemodelScreen *cms;
655 
656     CUBEMODEL_DISPLAY (s->display);
657     CUBE_SCREEN (s);
658 
659     cms = malloc (sizeof (CubemodelScreen));
660     if (!cms)
661 	return FALSE;
662 
663     s->base.privates[cmd->screenPrivateIndex].ptr = cms;
664 
665     cms->damage = FALSE;
666 
667     glLightfv (GL_LIGHT1, GL_AMBIENT, ambient);
668     glLightfv (GL_LIGHT1, GL_DIFFUSE, diffuse);
669     glLightfv (GL_LIGHT1, GL_SPECULAR, specular);
670 
671     initCubemodel (s);
672 
673     cubemodelSetModelFilenameNotify      (s, cubemodelLoadingOptionChange);
674     cubemodelSetModelAnimationNotify     (s, cubemodelLoadingOptionChange);
675 
676     cubemodelSetModelScaleFactorNotify   (s, cubemodelModelOptionChange);
677     cubemodelSetModelXOffsetNotify       (s, cubemodelModelOptionChange);
678     cubemodelSetModelYOffsetNotify       (s, cubemodelModelOptionChange);
679     cubemodelSetModelZOffsetNotify       (s, cubemodelModelOptionChange);
680     cubemodelSetModelRotationPlaneNotify (s, cubemodelModelOptionChange);
681     cubemodelSetModelRotationRateNotify  (s, cubemodelModelOptionChange);
682     cubemodelSetModelFpsNotify           (s, cubemodelModelOptionChange);
683     cubemodelSetRescaleWidthNotify       (s, cubemodelModelOptionChange);
684 
685     WRAP (cms, s, donePaintScreen, cubemodelDonePaintScreen);
686     WRAP (cms, s, preparePaintScreen, cubemodelPreparePaintScreen);
687     WRAP (cms, cs, clearTargetOutput, cubemodelClearTargetOutput);
688     WRAP (cms, cs, paintInside, cubemodelPaintInside);
689 
690     return TRUE;
691 }
692 
693 static void
cubemodelFiniScreen(CompPlugin * p,CompScreen * s)694 cubemodelFiniScreen (CompPlugin *p,
695 		     CompScreen *s)
696 {
697     CUBEMODEL_SCREEN (s);
698     CUBE_SCREEN (s);
699 
700     freeCubemodel (s);
701 
702     UNWRAP (cms, s, donePaintScreen);
703     UNWRAP (cms, s, preparePaintScreen);
704     UNWRAP (cms, cs, clearTargetOutput);
705     UNWRAP (cms, cs, paintInside);
706 
707     free (cms);
708 }
709 
710 static Bool
cubemodelInit(CompPlugin * p)711 cubemodelInit (CompPlugin *p)
712 {
713     cubemodelDisplayPrivateIndex = allocateDisplayPrivateIndex ();
714 
715     if (cubemodelDisplayPrivateIndex < 0)
716 	return FALSE;
717 
718     return TRUE;
719 }
720 
721 static void
cubemodelFini(CompPlugin * p)722 cubemodelFini (CompPlugin *p)
723 {
724     freeDisplayPrivateIndex (cubemodelDisplayPrivateIndex);
725 }
726 
727 static CompBool
cubemodelInitObject(CompPlugin * p,CompObject * o)728 cubemodelInitObject (CompPlugin *p,
729 		     CompObject *o)
730 {
731     static InitPluginObjectProc dispTab[] = {
732 	(InitPluginObjectProc) 0, /* InitCore */
733 	(InitPluginObjectProc) cubemodelInitDisplay,
734 	(InitPluginObjectProc) cubemodelInitScreen
735     };
736 
737     RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
738 }
739 
740 static void
cubemodelFiniObject(CompPlugin * p,CompObject * o)741 cubemodelFiniObject (CompPlugin *p,
742 		     CompObject *o)
743 {
744     static FiniPluginObjectProc dispTab[] = {
745 	(FiniPluginObjectProc) 0, /* FiniCore */
746 	(FiniPluginObjectProc) cubemodelFiniDisplay,
747 	(FiniPluginObjectProc) cubemodelFiniScreen
748     };
749 
750     DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
751 }
752 
753 CompPluginVTable cubemodelVTable = {
754     "cubemodel",
755     0,
756     cubemodelInit,
757     cubemodelFini,
758     cubemodelInitObject,
759     cubemodelFiniObject,
760     0,
761     0
762 };
763 
764 CompPluginVTable *
getCompPluginInfo(void)765 getCompPluginInfo (void)
766 {
767     return &cubemodelVTable;
768 }
769