/** * @brief Takes all of the brushes from the current entity and adds them to the world's brush list. * @note Used by func_group * @note This will only work if the func_group is the last entity currently known. At the moment, * this function is only called by ParseMapEntity and this happens directly after the func_group * is parsed, so this is OK. * @sa MoveModelToWorld */ static void MoveBrushesToWorld (entity_t* mapent) { int newbrushes, worldbrushes, i; mapbrush_t* temp; /* this is pretty gross, because the brushes are expected to be * in linear order for each entity */ newbrushes = mapent->numbrushes; worldbrushes = entities[0].numbrushes; if (newbrushes == 0) Sys_Error("Empty func_group - clean your map"); temp = Mem_AllocTypeN(mapbrush_t, newbrushes); memcpy(temp, mapbrushes + mapent->firstbrush, newbrushes * sizeof(*temp)); /* make space to move the brushes (overlapped copy) */ memmove(mapbrushes + worldbrushes + newbrushes, mapbrushes + worldbrushes, sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes)); /* copy the new brushes down */ memcpy(mapbrushes + worldbrushes, temp, sizeof(*temp) * newbrushes); /* fix up indexes */ entities[0].numbrushes += newbrushes; for (i = 1; i < num_entities; i++) entities[i].firstbrush += newbrushes; Mem_Free(temp); mapent->numbrushes = 0; }
static void WriteTGA24 (const char* filename, const byte* data, int width, int height, int offset) { const int size = width * height * 3; /* allocate a buffer and set it up */ byte* buffer = Mem_AllocTypeN(byte, size + TGA_HEADER_SIZE); memset(buffer, 0, TGA_HEADER_SIZE); buffer[2] = 2; buffer[12] = width & 255; buffer[13] = width >> 8; buffer[14] = height & 255; buffer[15] = height >> 8; buffer[16] = 24; /* create top-down TGA */ buffer[17] = 32; /* swap rgb to bgr */ for (int i = 0; i < size; i += 3) { buffer[i + TGA_HEADER_SIZE] = data[i*2 + offset + 2]; /* blue */ buffer[i + TGA_HEADER_SIZE + 1] = data[i*2 + offset + 1]; /* green */ buffer[i + TGA_HEADER_SIZE + 2] = data[i*2 + offset + 0]; /* red */ } /* write it and free the buffer */ ScopedFile file; if (FS_OpenFile(filename, &file, FILE_WRITE) > 0) Sys_Error("Unable to open %s for writing", filename); FS_Write(buffer, size + TGA_HEADER_SIZE, &file); /* close the file */ Mem_Free(buffer); }
void R_InitFBObjects (void) { unsigned int filters[2]; float scales[DOWNSAMPLE_PASSES]; int i; if (!r_config.frameBufferObject || !r_programs->integer) return; frameBufferObjectCount = 0; OBJZERO(frameBufferObjects); OBJZERO(frameBufferTextures); r_state.frameBufferObjectsInitialized = true; for (i = 0; i < DOWNSAMPLE_PASSES; i++) scales[i] = powf(DOWNSAMPLE_SCALE, i + 1); /* setup default screen framebuffer */ screenBuffer.fbo = 0; screenBuffer.depth = 0; screenBuffer.nTextures = 0; screenBuffer.width = viddef.context.width; screenBuffer.height = viddef.context.height; R_SetupViewport(&screenBuffer, 0, 0, viddef.context.width, viddef.context.height); Vector4Clear(screenBuffer.clearColor); /* use default framebuffer */ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); r_state.activeFramebuffer = &screenBuffer; colorAttachments = Mem_AllocTypeN(GLenum, r_config.maxDrawBuffers); for (i = 0; i < r_config.maxDrawBuffers; i++) colorAttachments[i] = GL_COLOR_ATTACHMENT0_EXT + i; filters[0] = GL_NEAREST; filters[1] = GL_LINEAR_MIPMAP_LINEAR; /* setup main 3D render target */ r_state.renderBuffer = R_CreateFramebuffer(viddef.context.width, viddef.context.height, 2, true, false, filters); /* setup bloom render targets */ fbo_bloom0 = R_CreateFramebuffer(viddef.context.width, viddef.context.height, 1, false, false, filters); fbo_bloom1 = R_CreateFramebuffer(viddef.context.width, viddef.context.height, 1, false, false, filters); filters[0] = GL_LINEAR; /* setup extra framebuffers */ for (i = 0; i < DOWNSAMPLE_PASSES; i++) { const int h = (int)((float)viddef.context.height / scales[i]); const int w = (int)((float)viddef.context.width / scales[i]); r_state.buffers0[i] = R_CreateFramebuffer(w, h, 1, false, false, filters); r_state.buffers1[i] = R_CreateFramebuffer(w, h, 1, false, false, filters); r_state.buffers2[i] = R_CreateFramebuffer(w, h, 1, false, false, filters); R_CheckError(); } }
/** * @brief Called before loading. Used to set default attribute values */ void uiGeoscapeNode::onLoading (uiNode_t* node) { Vector4Set(node->color, 1, 1, 1, 1); OBJZERO(EXTRADATA(node)); EXTRADATA(node).angles[YAW] = GLOBE_ROTATE; EXTRADATA(node).center[0] = EXTRADATA(node).center[1] = 0.5; EXTRADATA(node).zoom = 1.0; Vector2Set(EXTRADATA(node).smoothFinal2DGeoscapeCenter, 0.5, 0.5); VectorSet(EXTRADATA(node).smoothFinalGlobeAngle, 0, GLOBE_ROTATE, 0); /* @todo: allocate this on a per node basis - and remove the global variable geoscapeData */ EXTRADATA(node).geoscapeData = &geoscapeData; /* EXTRADATA(node).geoscapeData = Mem_AllocType(geoscapeData_t); */ /** this is the data that is used with r_dayandnightTexture */ EXTRADATA(node).r_dayandnightAlpha = Mem_AllocTypeN(byte, DAN_WIDTH * DAN_HEIGHT); r_dayandnightTexture = R_LoadImageData("***r_dayandnighttexture***", nullptr, DAN_WIDTH, DAN_HEIGHT, it_effect); r_radarTexture = R_LoadImageData("***r_radarTexture***", nullptr, RADAR_WIDTH, RADAR_HEIGHT, it_effect); r_xviTexture = R_LoadImageData("***r_xvitexture***", nullptr, XVI_WIDTH, XVI_HEIGHT, it_effect); }
bool Rimp_Init (void) { SDL_version version; int attrValue; Com_Printf("\n------- video initialization -------\n"); OBJZERO(r_sdl_config); if (r_driver->string[0] != '\0') { Com_Printf("using driver: %s\n", r_driver->string); SDL_GL_LoadLibrary(r_driver->string); } Sys_Setenv("SDL_VIDEO_CENTERED", "1"); Sys_Setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "0"); if (SDL_WasInit(SDL_INIT_VIDEO) == 0) { if (SDL_Init(SDL_INIT_VIDEO) < 0) Com_Error(ERR_FATAL, "Video SDL_Init failed: %s", SDL_GetError()); } SDL_VERSION(&version) Com_Printf("SDL version: %i.%i.%i\n", version.major, version.minor, version.patch); #if SDL_VERSION_ATLEAST(2,0,0) int screen = 0; const int modes = SDL_GetNumDisplayModes(screen); if (modes > 0) { r_sdl_config.modes = Mem_AllocTypeN(rect_t, modes); for (int i = 0; i < modes; i++) { SDL_DisplayMode displayMode; SDL_GetDisplayMode(screen, i, &displayMode); r_sdl_config.modes[i][0] = displayMode.w; r_sdl_config.modes[i][1] = displayMode.h; } } #else const SDL_VideoInfo* info = SDL_GetVideoInfo(); if (info != nullptr) { SDL_VideoInfo videoInfo; SDL_PixelFormat pixelFormat; SDL_Rect** modes; Com_Printf("I: desktop depth: %ibpp\n", info->vfmt->BitsPerPixel); r_config.videoMemory = info->video_mem; Com_Printf("I: video memory: %i\n", r_config.videoMemory); memcpy(&pixelFormat, info->vfmt, sizeof(pixelFormat)); memcpy(&videoInfo, info, sizeof(videoInfo)); videoInfo.vfmt = &pixelFormat; modes = SDL_ListModes(videoInfo.vfmt, SDL_OPENGL | SDL_FULLSCREEN); if (modes) { if (modes == (SDL_Rect**)-1) { Com_Printf("I: Available resolutions: any resolution is supported\n"); r_sdl_config.modes = nullptr; } else { for (r_sdl_config.numModes = 0; modes[r_sdl_config.numModes]; r_sdl_config.numModes++) {} r_sdl_config.modes = Mem_AllocTypeN(rect_t, r_sdl_config.numModes); for (int i = 0; i < r_sdl_config.numModes; i++) { r_sdl_config.modes[i][0] = modes[i]->w; r_sdl_config.modes[i][1] = modes[i]->h; } } } else { Com_Printf("I: Could not get list of available resolutions\n"); } } char videoDriverName[MAX_VAR] = ""; SDL_VideoDriverName(videoDriverName, sizeof(videoDriverName)); Com_Printf("I: video driver: %s\n", videoDriverName); #endif if (r_sdl_config.numModes > 0) { char buf[4096] = ""; Q_strcat(buf, sizeof(buf), "I: Available resolutions:"); for (int i = 0; i < r_sdl_config.numModes; i++) { Q_strcat(buf, sizeof(buf), " %ix%i", r_sdl_config.modes[i][0], r_sdl_config.modes[i][1]); } Com_Printf("%s (%i)\n", buf, r_sdl_config.numModes); } if (!R_SetMode()) Com_Error(ERR_FATAL, "Video subsystem failed to initialize"); #if !SDL_VERSION_ATLEAST(2,0,0) SDL_WM_SetCaption(GAME_TITLE, GAME_TITLE_LONG); /* we need this in the renderer because if we issue an vid_restart we have * to set these values again, too */ SDL_EnableUNICODE(SDL_ENABLE); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); #endif R_SetSDLIcon(); if (!SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &attrValue)) Com_Printf("I: got %d bits of stencil\n", attrValue); if (!SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &attrValue)) Com_Printf("I: got %d bits of depth buffer\n", attrValue); if (!SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &attrValue)) Com_Printf("I: got double buffer\n"); if (!SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &attrValue)) Com_Printf("I: got %d bits for red\n", attrValue); if (!SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &attrValue)) Com_Printf("I: got %d bits for green\n", attrValue); if (!SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &attrValue)) Com_Printf("I: got %d bits for blue\n", attrValue); if (!SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &attrValue)) Com_Printf("I: got %d bits for alpha\n", attrValue); if (!SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &attrValue)) Com_Printf("I: got multisample %s\n", attrValue != 0 ? "enabled" : "disabled"); if (!SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &attrValue)) Com_Printf("I: got %d multisample buffers\n", attrValue); return true; }
/** * @brief * @sa FinalLightFace */ void BuildFacelights (unsigned int facenum) { dBspSurface_t* face; dBspPlane_t* plane; dBspTexinfo_t* tex; float* center; float* sdir, *tdir; vec3_t normal, binormal; vec4_t tangent; lightinfo_t li; float scale; int i, j, numsamples; facelight_t* fl; int* headhints; const int grid_type = config.soft ? 1 : 0; if (facenum >= MAX_MAP_FACES) { Com_Printf("MAX_MAP_FACES hit\n"); return; } face = &curTile->faces[facenum]; plane = &curTile->planes[face->planenum]; tex = &curTile->texinfo[face->texinfo]; if (tex->surfaceFlags & SURF_WARP) return; /* non-lit texture */ sdir = tex->vecs[0]; tdir = tex->vecs[1]; /* lighting -extra antialiasing */ if (config.extrasamples) numsamples = config.soft ? SOFT_SAMPLES : MAX_SAMPLES; else numsamples = 1; OBJZERO(li); scale = 1.0 / numsamples; /* each sample contributes this much */ li.face = face; li.facedist = plane->dist; VectorCopy(plane->normal, li.facenormal); /* negate the normal and dist */ if (face->side) { VectorNegate(li.facenormal, li.facenormal); li.facedist = -li.facedist; } /* get the origin offset for rotating bmodels */ VectorCopy(face_offset[facenum], li.modelorg); /* calculate lightmap texture mins and maxs */ CalcLightinfoExtents(&li); /* and the lightmap texture vectors */ CalcLightinfoVectors(&li); /* now generate all of the sample points */ CalcPoints(&li, 0, 0); fl = &facelight[config.compile_for_day][facenum]; fl->numsamples = li.numsurfpt; fl->samples = Mem_AllocTypeN(vec3_t, fl->numsamples); fl->directions = Mem_AllocTypeN(vec3_t, fl->numsamples); center = face_extents[facenum].center; /* center of the face */ /* Also setup the hints. Each hint is specific to each light source, including sunlight. */ headhints = Mem_AllocTypeN(int, (numlights[config.compile_for_day] + 1)); /* calculate light for each sample */ for (i = 0; i < fl->numsamples; i++) { float* const sample = fl->samples[i]; /* accumulate lighting here */ float* const direction = fl->directions[i]; /* accumulate direction here */ if (tex->surfaceFlags & SURF_PHONG) /* interpolated normal */ SampleNormal(&li, li.surfpt[i], normal); else /* or just plane normal */ VectorCopy(li.facenormal, normal); for (j = 0; j < numsamples; j++) { /* with antialiasing */ vec3_t pos; /* add offset for supersampling */ VectorMA(li.surfpt[i], sampleofs[grid_type][j][0] * li.step, li.textoworld[0], pos); VectorMA(pos, sampleofs[grid_type][j][1] * li.step, li.textoworld[1], pos); NudgeSamplePosition(pos, normal, center, pos); GatherSampleLight(pos, normal, sample, direction, scale, headhints); } if (VectorNotEmpty(direction)) { vec3_t dir; /* normalize it */ VectorNormalize(direction); /* finalize the lighting direction for the sample */ TangentVectors(normal, sdir, tdir, tangent, binormal); dir[0] = DotProduct(direction, tangent); dir[1] = DotProduct(direction, binormal); dir[2] = DotProduct(direction, normal); VectorCopy(dir, direction); } } /* Free the hints. */ Mem_Free(headhints); for (i = 0; i < fl->numsamples; i++) { /* pad them */ float* const direction = fl->directions[i]; if (VectorEmpty(direction)) VectorSet(direction, 0.0, 0.0, 1.0); } /* free the sample positions for the face */ Mem_Free(li.surfpt); }
/** * @brief Fills in texorg, worldtotex. and textoworld */ static void CalcLightinfoVectors (lightinfo_t* l) { const dBspTexinfo_t* tex; int i; vec3_t texnormal; vec_t distscale, dist; tex = &curTile->texinfo[l->face->texinfo]; for (i = 0; i < 2; i++) VectorCopy(tex->vecs[i], l->worldtotex[i]); /* calculate a normal to the texture axis. points can be moved along this * without changing their S/T */ texnormal[0] = tex->vecs[1][1] * tex->vecs[0][2] - tex->vecs[1][2] * tex->vecs[0][1]; texnormal[1] = tex->vecs[1][2] * tex->vecs[0][0] - tex->vecs[1][0] * tex->vecs[0][2]; texnormal[2] = tex->vecs[1][0] * tex->vecs[0][1] - tex->vecs[1][1] * tex->vecs[0][0]; VectorNormalize(texnormal); /* flip it towards plane normal */ distscale = DotProduct(texnormal, l->facenormal); if (!distscale) { Verb_Printf(VERB_EXTRA, "WARNING: Texture axis perpendicular to face\n"); distscale = 1.0; } if (distscale < 0.0) { distscale = -distscale; VectorSubtract(vec3_origin, texnormal, texnormal); } /* distscale is the ratio of the distance along the texture normal to * the distance along the plane normal */ distscale = 1.0 / distscale; for (i = 0; i < 2; i++) { const vec_t len = VectorLength(l->worldtotex[i]); const vec_t distance = DotProduct(l->worldtotex[i], l->facenormal) * distscale; VectorMA(l->worldtotex[i], -distance, texnormal, l->textoworld[i]); VectorScale(l->textoworld[i], (1.0f / len) * (1.0f / len), l->textoworld[i]); } /* calculate texorg on the texture plane */ for (i = 0; i < 3; i++) l->texorg[i] = -tex->vecs[0][3] * l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i]; /* project back to the face plane */ dist = DotProduct(l->texorg, l->facenormal) - l->facedist - 1; dist *= distscale; VectorMA(l->texorg, -dist, texnormal, l->texorg); /* compensate for org'd bmodels */ VectorAdd(l->texorg, l->modelorg, l->texorg); /* total sample count */ l->numsurfpt = l->texsize[0] * l->texsize[1]; l->surfpt = Mem_AllocTypeN(vec3_t, l->numsurfpt); if (!l->surfpt) Sys_Error("Surface too large to light (" UFO_SIZE_T ")", l->numsurfpt * sizeof(*l->surfpt)); /* distance between samples */ l->step = 1 << config.lightquant; }